silky微服務簡介

代理主機

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

通用代理主機

該類型的主機通常用於託管業務應用,服務內部之間經過rpc進行通訊,不支持與微服務集羣與外部進行通訊,web代理主機能夠經過引用該類型的微服務的應用接口,經過應用接口生成的代理與該微服務進行通訊。該類型的微服務使用.net的通用主機進行託管引用。定義的Startup模塊以下所示:git

[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,並指定啓動模塊便可。github

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提供的模塊。web

啓動模塊以下所示:redis

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

}

web代理主機

該類型的主機能夠經過http端口與外部經過http協議進行通訊,經過引用其餘業務微服務應用的應用接口,根據路由模版生成restful風格的webapi,開發者能夠經過配置生成在線的swagger文檔。直觀的看到在線api文檔和進行調試。生成的swagger文檔能夠根據引用的應用接口進行分組。算法

image

web代理主機預約義的Startup模塊指定了web代理主機必須依賴的silky模塊,以下所示:docker

[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類。shell

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類以下所示:json

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/

相關文章
相關標籤/搜索