silky微服務簡介

Silky發表於2021-11-01

代理主機

silky微服務定義了三種型別的代理主機,開發者可以根據需要選擇合適的silky代理主機託管微服務應用。代理主機定義了一個Startup模組,該模組給出了使用該種型別主機所必須依賴的模組。

通用代理主機

該型別的主機一般用於託管業務應用,服務內部之間通過rpc進行通訊,不支援與微服務叢集與外部進行通訊,web代理主機可以通過引用該型別的微服務的應用介面,通過應用介面生成的代理與該微服務進行通訊。該型別的微服務使用.net的通用主機進行託管引用。定義的Startup模組如下所示:

  [DependsOn(typeof(ZookeeperModule),
        typeof(DotNettyTcpModule),
        typeof(RpcProxyModule),
        typeof(TransactionTccModule),
        typeof(ValidationModule),
        typeof(FluentValidationModule),
        typeof(RedisCachingModule),
        typeof(TransactionRepositoryRedisModule)
    )]
    public abstract class GeneralHostModule : StartUpModule
    {
    }

開發者如果需要建立一個微服務應用,只需要在建立一個控制檯應用,通過nuget包管理工具安裝Silky.Agent.GeneralHost包,在主函式中註冊SilkyServices,並指定啟動模組即可。


   public static async Task Main(string[] args)
   {
       await CreateHostBuilder(args).Build().RunAsync();
   }

    private static IHostBuilder CreateHostBuilder(string[] args)
    {
        return Host.CreateDefaultBuilder(args)
            .RegisterSilkyServices<AccountHostModule>()
        ;
    }

開發者通過繼承GeneralHostModule模組定義啟動模組。可以通過DependsOn依賴自定義的模組或是Silky提供的模組。

啟動模組如下所示:

// 
//  [DependsOn(typeof(SilkySkyApmAgentModule),
//         typeof(JwtModule),
//         typeof(MessagePackModule))]
public class AccountHostModule : GeneralHostModule
{

}

web代理主機

該型別的主機可以通過http埠與外部通過http協議進行通訊,通過引用其他業務微服務應用的應用介面,根據路由模版生成restful風格的webapi,開發者可以通過配置生成線上的swagger文件。直觀的看到線上api文件和進行除錯。生成的swagger文件可以根據引用的應用介面進行分組。

image

web代理主機預定義的Startup模組指定了web代理主機必須依賴的silky模組,如下所示:

    [DependsOn(typeof(RpcProxyModule),
       typeof(ZookeeperModule),
       typeof(SilkyHttpCoreModule),
       typeof(DotNettyModule),
       typeof(ValidationModule),
       typeof(FluentValidationModule),
       typeof(RedisCachingModule)
   )]
    public abstract class WebHostModule : StartUpModule
    {

    }

該型別的主機一般用於閘道器,提供了外部與微服務叢集進行通訊的橋樑,該型別的主機使用.net的web主機進行託管應用。開發者可以建立一個aspnetcore專案,通過安裝Silky.Agent.WebHost包即可建立web代理主機,需要同時指定啟動模組和Startup類。

    public async static Task Main(string[] args)
    {
        await CreateHostBuilder(args).Build().RunAsync();
    }

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        var hostBuilder = Host.CreateDefaultBuilder(args)
            .RegisterSilkyServices<GatewayHostModule>()
            .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });

        return hostBuilder;
    }

web代理主機的啟動模組需要繼承WebHostModule,啟動模組GatewayHostModule如下所示:

public class GatewayHostModule : WebHostModule
{
    
}

需要在Startup類註冊Silky請求管道,Startup類如下所示:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment() || env.EnvironmentName == "ContainerDev")
        {
            app.UseDeveloperExceptionPage();
        }
        app.ConfigureSilkyRequestPipeline();
    }
}

websocket代理主機

websocket代理主機與通用代理主機基本一致,websocket代理主機具體提供ws服務的能力,web主機可以通過ws代理與websocket代理主機的ws服務進行通訊。

websocket代理主機的啟動模組如下所示:

    [DependsOn(typeof(ZookeeperModule),
        typeof(DotNettyTcpModule),
        typeof(RpcProxyModule),
        typeof(TransactionTccModule),
        typeof(WebSocketModule),
        typeof(ValidationModule),
        typeof(FluentValidationModule),
        typeof(RedisCachingModule),
        typeof(TransactionRepositoryRedisModule)
        )]
    public abstract class WebSocketHostModule : StartUpModule
    {
    }

開發者可以通過WebSocket配置節點對ws服務進行配置,ws服務的預設埠為3000,但是一般地,與ws服務建立握手時,不應該與ws服務直接進行握手,而是應該通過web代理主機的代理中介軟體進行握手,所以如果開發者使用ws服務,必須要在web代理主機安裝Silky.WebSocket.Middleware

ws服務的建立與通用代理主機的建立一致,只需要將啟動模組繼承的基類修改為WebSocketHostModule即可。

ws服務的定義如下:

    public class WsTestAppService : WsAppServiceBase, IWsTestAppService
    {
        public async Task Echo(string businessId, string msg)
        {
            if (BusinessSessionIds.TryGetValue(businessId, out var sessionIds))
            {
                foreach (var sessionId in sessionIds)
                {
                    SessionManager.SendTo($"message:{msg},sessionId:{sessionId}", sessionId);
                }
            }
            else
            {
                throw new BusinessException($"不存在businessId為{businessId}的會話");
            }
        }
    }

需要注意的時,在建立握手過程中,必須要指定hashkey從而保證每次回話的微服務例項都是同一個,更多關於ws服務請檢視

分散式事務

silky微服務使用攔截器和filter實現了TCC分散式事務,在tcc分散式事務過程中,將事務參與者的呼叫引數作為undolog日誌儲存到資料倉儲中(當前實現了redis作為undo日誌的資料儲存器),並在後臺執行作業檢查分散式事務的執行情況,從而保證資料的最終一致性。

分散式事務的使用

  1. 在應用介面中通過[Transaction]特性進行標識該介面是一個分散式應用方法。
[Transaction]
Task<GetOrderOutput> Create(CreateOrderInput input);
  1. 應用服務實現通過[TccTransaction]特性標識,並指定ConfirmMethod方法和CancelMethod,指定實現的ConfirmMethod方法和CancelMethod必須為public,方法引數與應用實現方法的保持一致。try方法如果需要向ConfirmMethod方法和CancelMethod傳遞引數通過RpcContext.Context進行。
        [TccTransaction(ConfirmMethod = "OrderCreateConfirm", CancelMethod = "OrderCreateCancel")]
        [UnitOfWork]
        public async Task<GetOrderOutput> Create(CreateOrderInput input)
        {
            var orderOutput = await _orderDomainService.Create(input);
            return orderOutput;
        }

        [UnitOfWork]
        public async Task<GetOrderOutput> OrderCreateConfirm(CreateOrderInput input)
        {
            var orderId = RpcContext.Context.GetAttachment("orderId");
            var order = await _orderDomainService.GetById(orderId.To<long>());
            order.Status = OrderStatus.Payed;
            order.UpdateTime = DateTime.Now;
            order = await _orderDomainService.Update(order);
            return order.Adapt<GetOrderOutput>();
        }
        
        [UnitOfWork]
        public async Task OrderCreateCancel(CreateOrderInput input)
        {
            var orderId = RpcContext.Context.GetAttachment("orderId");
            if (orderId != null)
            {
                // await _orderDomainService.Delete(orderId.To<long>());
                var order = await _orderDomainService.GetById(orderId.To<long>());
                order.Status = OrderStatus.UnPay;
                await _orderDomainService.Update(order);
            }
        }

服務定義與RPC通訊

應用介面的定義

silky的服務定義非常簡單,在這裡的服務指的是應用服務,與傳統MVC的Controller的概念一致。

您只需要在一個業務微服務應用中,新增應用介面層,一般地,我們可以命名為Project.IApplication或是Project.Application.Contracts,並新增應用介面,在應用介面中通過[ServiceRoute]特性進行標識,並在Project.Application專案中實現該介面。

您可以通過[ServiceRoute]指定該應用服務的路由模板, 以及是否允許多個實現。

例如:


namespace Silky.Account.Application.Contracts.Accounts
{
    /// <summary>
    /// 賬號服務
    /// </summary>
    [ServiceRoute]
    public interface IAccountAppService
    {
        /// <summary>
        /// 新增賬號
        /// </summary>
        /// <param name="input">賬號資訊</param>
        /// <returns></returns>
        Task<GetAccountOutput> Create(CreateAccountInput input);
    }
}

在應用層中實現該介面:

namespace Silky.Account.Application.Accounts
{
    public class AccountAppService : IAccountAppService
    {
        private readonly IAccountDomainService _accountDomainService;


        public AccountAppService(IAccountDomainService accountDomainService)
        {
            _accountDomainService = accountDomainService;
        }

        public async Task<GetAccountOutput> Create(CreateAccountInput input)
        {
            var account = await _accountDomainService.Create(input);
            return account.Adapt<GetAccountOutput>();
        }
    }
}

RPC通訊

應用介面可以被其他微服務應用或是被閘道器應用引用。其他微服務可以通過應用介面生成代理,並通過內部實現的rpc框架與該微服務進行通訊。silky的rpc通訊支援tcc方式的分散式事務,詳情見上節。

應用介面被閘道器引用,web host主機可以通過該應用服務介面生成相應的webapi,並可以生成swagger線上文件。通過http請求,從而實現服務與叢集外部進行通訊,當http請求到達webhost主機後,silky中介軟體通過webapi和請求方法路由到服務條目,然後通過內部實現的rpc通訊與微服務應用進行通訊。

RPC的過濾器: rpc通訊支援兩種型別的過濾器,在客戶端發起請求過程中,會依次呼叫開發者定義的IClientFilter過濾器,服務端收到請求後,會依次呼叫IServerFilter然後再執行應用方法本身。

RpcContext: 可以通過RpcContext.Context新增或是獲取本次rpc呼叫的Attachments引數。當然,開發者也可以通過注入IRpcContextAccessor獲取本次通訊的上線文引數RpcContext

獲取當前登入使用者: 開發者可以通過NullSession.Instance獲取當前登入使用者,如果您已經登入系統,那麼通過該介面可以獲取到當前登入使用者的userIduserName等資訊。

服務治理

針對每個服務條目(應用服務介面方法),都實現了服務治理,開發者可以通過governance或是[Governance()]特性對服務的最大併發量、負載均衡演算法、執行超時時間、是否使用快取攔截、失敗回撥介面、介面是否對外網遮蔽等等屬性進行配置。

以下描述了以服務條目為治理單位的屬性表單:

屬性 說明 預設值 備註
AddressSelectorMode 負載均衡策略 Polling(輪詢) 負載均衡演算法支援:Polling(輪詢)、Random(隨機)、HashAlgorithm(雜湊一致性,根據rpc引數的第一個引數值)
ExecutionTimeout 執行超時時間 3000(ms) 單位為(ms),超時時發生熔斷,-1表示在rpc通訊過程中不會超時
CacheEnabled 是否啟用快取攔截 true rpc通訊中是否啟用快取攔截
MaxConcurrent 允許的最大併發量 100
FuseProtection 是否開啟熔斷保護 true
FuseSleepDuration 熔斷休眠時長 60(s) 發生熔斷後,多少時長後再次重試該服務例項
FuseTimes 服務提供者允許的熔斷次數 3 服務例項連續n次發生熔斷端,服務例項將被標識為不健康
FailoverCount 故障轉移次數 0 rpc通訊異常情況下,允許的重新路由服務例項的次數,0表示有幾個服務例項就轉移幾次
ProhibitExtranet 是否禁止外網訪問 false 該屬性只允許通過GovernanceAttribute特性進行設定
FallBackType 失敗回撥指定的型別 null 型別為Type,如果指定了失敗回撥型別,那麼在服務執行失敗,則會執行該型別的Invoke方法,該型別,必須要繼承IFallbackInvoker該介面

開發者還可以通過[Governance()]特性對某個服務方法進行標識,被該特性標識的治理屬性將覆蓋微服務的配置/預設值。

快取攔截

為提高應用的響應,silky支援快取攔截。快取攔截在應用服務介面方法上通過快取攔截特性進行設定,在silky框架中,存在如下三中型別的快取特性,分別對資料快取進行新增、更新、刪除。

  1. 設定快取特性--GetCachingInterceptAttribute

  2. 更新快取特性--UpdateCachingInterceptAttribute

  3. 刪除快取特性--RemoveCachingInterceptAttribute

使用快取攔截,必須要保證快取一致性。在rpc通訊過程中,使用快取攔截,同一資料的快取依據可能會不同(設定的KeyTemplate,例如:快取依據可能會根據IdNameCode分別進行快取),從而產生不同的快取資料,但是在對資料進行更新、刪除操作時,由於無法通過RemoveCachingInterceptAttribute特性一次性刪除該型別資料的所有快取資料,這個時候,在實現業務程式碼過程中,就需要通過分散式快取介面IDistributedCache<T>實現快取資料的更新、刪除操作。

服務註冊中心

silky使用zookeeper作為預設服務的註冊中心。當前還未擴充套件支援其他的服務註冊中心。

silky支援為微服務叢集配置多個服務註冊中心,您只需要在配置服務註冊中心的連結字串registrycenter:connectionStrings中,使用分號;就可以指定微服務框架的多個服務註冊中心。

為微服務配置服務註冊中心如下所示:

registrycenter: // 服務註冊中心配置節點
  connectionStrings: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183;127.0.0.1:2184,127.0.0.1:2185,127.0.0.1:2186 // 服務配置中心連結
  registryCenterType: Zookeeper // 註冊中心型別
  connectionTimeout: 1000 // 連結超時時間(單位:ms)
  sessionTimeout: 2000 // 會話超時時間(單位:ms)
  operatingTimeout: 4000 // 操作超時時間(單位:ms)
  routePath: /services/serviceroutes

模組化管理

silky框架存在兩種型別的模組:

  1. 開發者通過繼承SilkyModule就可以定義一個普通模組類;
  2. 也可以通過繼承StartUpModule定義一個服務註冊啟動模組類;開發者也可以通過繼承StartUpModule,選擇合適的依賴包,實現自己的代理主機。

模組的依賴關係: silky框架的模組通過DependsOn特性指定模組的依賴關係,silky框架支援通過直接或是間接的依賴模組。

依賴注入(服務註冊與解析)

  1. 通過繼承依賴注入標識介面實現服務的註冊(推薦)
    silky框架提供了三個依賴註冊的相關標識介面:ISingletonDependency(單例模式)、IScopedDependency(區域模式)、ITransientDependency(瞬態模式)。在微服務應用啟動時,會掃描繼承了這些標識介面的類(服務),並將其自身和繼承的介面註冊到Ioc容器中。

  2. 定義模組,並在模組中通過RegisterServices()方法的ContainerBuilder註冊服務(autofac),或是通過ConfigureServices()方法的IServiceCollection註冊服務(微軟官方自帶的ioc容器)

  3. 通過繼承IConfigureService或是ISilkyStartup,通過Configure()方法的IServiceCollection註冊服務

Silky因為支援通過IServiceCollection進行服務註冊,所以可以很方便的與第三方服務(元件)進行整合,例如:CAP或是MassTransit等分散式事件框架。

使用Serilog作為日誌記錄器

silky框架提供了serilog作為日誌記錄器。只需要在構建主機時,增加UseSerilogDefault(),並新增Serilog相關配置即可。

程式碼:

public static async Task Main(string[] args)
{
    await CreateHostBuilder(args).Build().RunAsync();
}

private static IHostBuilder CreateHostBuilder(string[] args)
{
    var hostBuilder = Host.CreateDefaultBuilder(args)
        .RegisterSilkyServices<OrderHostModule>()
        .UseSerilogDefault();
    return hostBuilder;
}

配置:

serilog:
  minimumLevel:
    default: Information
    override:
      Microsoft: Warning
      Microsoft.Hosting.Lifetime: Information
      Silky: Debug
  writeTo:
    - name: File
      args:
        path: "./logs/log-.log"
        rollingInterval: Day
    - name: Console
      args:
        outputTemplate: "[{Timestamp:yyyy/MM/dd HH:mm:ss} {Level:u11}] {Message:lj} {NewLine}{Exception}{NewLine}"
        theme: "Serilog.Sinks.SystemConsole.Themes.SystemConsoleTheme::Literate, Serilog.Sinks.Console"

使用Miniprofile對http請求進行效能監控

要求必須在web主機專案(一般為閘道器專案)安裝Silky.Http.MiniProfiler包,並將swaggerDocument:injectMiniProfiler配置項的屬性設定為true

swaggerDocument:
  injectMiniProfiler: true

image

使用skywalking檢視鏈路跟蹤

要求微服務在啟動模組依賴SilkySkyApmAgentModule模組,並配置skyWalking相關屬性。

 [DependsOn(typeof(SilkySkyApmAgentModule))]
public class AccountHostModule : GeneralHostModule
{
}
skyWalking:
  serviceName: AccountHost
  headerVersions:
    - sw8
  sampling:
    samplePer3Secs: -1
    percentage: -1.0
  logging:
    level: Debug
    filePath: "logs/skyapm-{Date}.log"
  transport:
    interval: 3000
    protocolVersion: v8
    queueSize: 30000
    batchSize: 3000
    gRPC:
      servers: "127.0.0.1:11800"
      timeout: 10000
      connectTimeout: 10000
      reportTimeout: 600000

在silky的例項專案中,提供了skyWalking通過docker-compose快速啟動的服務編排檔案samples\docker-compose\infrastr\docker-compose.skywalking.yml,開發者只需要進入到samples\docker-compose\infrastr目錄中,通過如下命令即可開始的啟動一個skyWalking服務。

cd samples\docker-compose\infrastr
docker-compose -f docker-compose.skywalking.yml

開啟http://127.0.0.1:8180即可看到微服務叢集的執行情況:

網路拓撲圖:

image

鏈路跟蹤:

image

儀表盤:

image

使用Apollo作為服務配置中心

部署Apollo服務

必要前提是開發者已經部署了一套Apollo服務。開發者可以參考Apollo部署節點,部署一套Apollo服務。

在開發過程中,更簡單的做法是使用silky例項專案中使用docker-compose已經編排好的檔案 docker-compose.apollo.yml

進入到samples\docker-compose\infrastr目錄,將.env設定的環境變數EUREKA_INSTANCE_IP_ADDRESS修改為您當前本機的IP地址,不允許為127.0.0.1

執行如下命令,等待1~2分鐘即可啟動apollo配置服務。

docker-compose -f docker-compose.apollo.yml up -d

使用Apollo作為微服務的配置中心

  1. 在主機專案通過nuget安裝Silky.Apollo包。(這是一個空包,您也可以直接安裝Com.Ctrip.Framework.Apollo.AspNetCoreHostingCom.Ctrip.Framework.Apollo.Configuration包)

  2. 在服務註冊時,新增對Appo服務配置中心的支援

private static IHostBuilder CreateHostBuilder(string[] args)
{
    return Host.CreateDefaultBuilder(args)
        .RegisterSilkyServices<AccountHostModule>()
        .AddApollo();
}

如果您您想在指定的執行環境中使用Apollo作為微服務的配置中心,而在另外其他執行環境中使用本地配置,那麼您也可以通過如下當時處理:

private static IHostBuilder CreateHostBuilder(string[] args)
{
    var hostBuilder = Host.CreateDefaultBuilder(args)
        .RegisterSilkyServices<AccountHostModule>()
        .UseSerilogDefault();
    if (EngineContext.Current.IsEnvironment("Apollo"))
    {
        hostBuilder.AddApollo();
    }

    return hostBuilder;
}

備註
執行環境您可以通過修改Properties\launchSettings.jsonDOTNET_ENVIRONMENT變數(本地開發模式)
或是通過.env環境變數檔案指定DOTNET_ENVIRONMENT變數(docker-compose開發模式)

  1. 在Apollo服務配置中心新建相關的應用,並新增相關的配置

開啟地址:http://127.0.0.1:8070 (Applo服務的web管理工具:portal),新建相關的應用。如下圖:

image

為應用新增相應的配置:

image

普通業務微服務的配置如下:

# Application
rpc:port = 2201
connectionStrings:default = server=127.0.0.1;port=3306;database=order;uid=root;pwd=qwe!P4ss;
jwtSettings:secret = jv1PZkwjLVCEygM7faLLvEhDGWmFqRUW

# TEST1.silky.sample
registrycenter:registryCenterType = Zookeeper
registrycenter:connectionStrings = 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183;127.0.0.1:2184,127.0.0.1:2185,127.0.0.1:2186

distributedCache:redis:isEnabled = true
distributedCache:redis:configuration = 127.0.0.1:6379,defaultDatabase=0

rpc:token = ypjdYOzNd4FwENJiEARMLWwK0v7QUHPW

governance:executionTimeout = -1

cap:rabbitmq:hostName = 127.0.0.1
cap:rabbitmq:userName = rabbitmq
cap:rabbitmq:password = rabbitmq

web閘道器的配置如下:


# TEST1.silky.sample.gateway
gateway:injectMiniProfiler = true
gateway:enableSwaggerDoc = true
gateway:wrapResult = true
gateway:jwtSecret = jaoaNPA1fo1rcPfK23iNufsQKkhTy8eh
swaggerDocument:organizationMode = Group
swaggerDocument:injectMiniProfiler = true
swaggerDocument:termsOfService = https://www.github.com/liuhll/silky

# TEST1.silky.sample
registrycenter:registryCenterType = Zookeeper
registrycenter:connectionStrings = 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183;127.0.0.1:2184,127.0.0.1:2185,127.0.0.1:2186

distributedCache:redis:isEnabled = true
distributedCache:redis:configuration = 127.0.0.1:6379,defaultDatabase=0

rpc:token = ypjdYOzNd4FwENJiEARMLWwK0v7QUHPW

governance:executionTimeout = -1
  1. 增加Apollo配置中心相關配置(預設讀取appsettings.yml),如果指定執行環境變數則讀取appsettings.{Environment}.yml中的配置

例如:

apollo:
  appId: "silky-stock-host"
  cluster: default
  metaServer: "http://127.0.0.1:8080/"
  #  secret: "ffd9d01130ee4329875ac3441c0bedda"
  namespaces:
    - application
    - TEST1.silky.sample
  env: DEV
  meta:
    DEV: "http://127.0.0.1:8080/"
    PRO: "http://127.0.0.1:8080/"

分散式鎖

silky使用DistributedLock作為分散式鎖,在服務路由註冊和分散式事務作業中均使用了分散式鎖.

身份認證與授權

silky身份認證與授權通過包Silky.Http.Identity,通過webhost在閘道器實現統一的身份認證和授權。

使用者登陸與簽發token

silky通過Silky.Jwt包提供的IJwtTokenGenerator實現jwt格式的token。簽發token的微服務應用需要通過nuget安裝Silky.Jwt包,並在啟動模組中依賴JwtModule模組。開發者可以對簽發的token的金鑰、token有效期、Jwt簽名演算法、簽發者、受眾等屬性通過配置節點jwtSettings進行配置。開發者至少需要對jwtSettings:secret進行配置。

配置如下:

jwtSettings:
  secret: jv1PZkwjLVCEygM7faLLvEhDGWmFqRUW

使用者登陸介面如下:

        public async Task<string> Login(LoginInput input)
        {
            var userInfo = await _accountRepository.FirstOrDefaultAsync(p => p.UserName == input.Account
                                                                             || p.Email == input.Account);
            if (userInfo == null)
            {
                throw new AuthenticationException($"不存在賬號為{input.Account}的使用者");
            }

            if (!userInfo.Password.Equals(_passwordHelper.EncryptPassword(userInfo.UserName, input.Password)))
            {
                throw new AuthenticationException("密碼不正確");
            }

            var payload = new Dictionary<string, object>()
            {
                { ClaimTypes.UserId, userInfo.Id },
                { ClaimTypes.UserName, userInfo.UserName },
                { ClaimTypes.Email, userInfo.Email },
            };
            return _jwtTokenGenerator.Generate(payload);
        }

身份認證

  1. 閘道器專案(WebHost)的啟動模組需要依賴IdentityModule模組
    [DependsOn(typeof(IdentityModule))]
    public class GatewayHostModule : WebHostModule
    {
        
    }
  1. gateway:jwtSecret配置的屬性必須與簽發token的微服務應用配置的屬性jwtSettings:secret的值保持一致。
gateway:
  jwtSecret: jv1PZkwjLVCEygM7faLLvEhDGWmFqRUW
  1. 匿名訪問

開發者只需要在應用介面或是應用介面方法中標註[AllowAnonymous]特性即可,這樣無需使用者登陸,也可以訪問該介面。

[AllowAnonymous]
Task<string> Login(LoginInput input);

授權

開發者可以在閘道器應用通過繼承SilkyAuthorizationHandler基類,並重寫PipelineAsync方法即可實現對自定義授權。

 public class TestAuthorizationHandler : SilkyAuthorizationHandler
    {
        private readonly ILogger<TestAuthorizationHandler> _logger;
        private readonly IAuthorizationAppService _authorizationAppService;

        public TestAuthorizationHandler(ILogger<TestAuthorizationHandler> logger,
        IAuthorizationAppService authorizationAppService)
        {
            _logger = logger;
           _authorizationAppService = authorizationAppService;
        }

        public async override Task<bool> PipelineAsync(AuthorizationHandlerContext context,
            DefaultHttpContext httpContext)
        {
            // 獲取訪問的服務條目
            var serviceEntry = httpContext.GetServiceEntry();
           
            // 可以通過rpc呼叫IdentifyApp,實現自定義的授權 
           return _authorizationAppService.Authorization(sserviceEntry.ServiceDescriptor.Id);
           
        }
    }

物件屬性對映

silky實現了基於AutoMapperMapster的物件屬性對映的包。實現的代理主機預設依賴MapsterModule包,使用Mapster作為物件對映的元件。

只需要通過Adapt方法即可實現物件屬性對映。

使用efcore作為資料訪問元件

efcore資料訪問元件主要參考了furion的實現。提供了資料倉儲、資料庫定位器、多租戶等實現方式。使用方式與其基本保持一致。

silky開源地址

github: https://github.com/liuhll/silky

gitee: https://gitee.com/liuhll2/silky

開發者文件: http://docs.silky-fk.com/

相關文章