silky微服務業務主機簡介

Silky發表於2021-11-11

主機的概念

silky的主機與.net的主機概念一致。是封裝應用資源的物件,用於託管應用和管理應用的生命週期。

通用主機

如果用於託管普通的業務應用,該微服務模組本身並不需要對直接對叢集外部提供訪問入口。那麼,您可以使用.net的通用主機註冊silky服務框架。.net的通用主機無法提供http請求,也無法配置http的請求管道(即:中介軟體)。

在註冊silky框架後,silky框架會註冊dotnetty的服務監聽者,並會暴露rpc埠號。但是由於silky框架的安全機制,叢集外部並不允許通過tcp協議通過rpc埠號直接訪問該微服務模組的應用介面。

web主機

如果您需要訪問該服務模組的應用介面,您必須要通過.net的web主機註冊silky框架,並配置silky框架的請求管道。這樣,web構建的主機通過引用某個微服務的應用介面專案(包),通過應用介面的代理與微服務叢集內部實現rpc通訊。

業務主機型別

silky微服務框架提供了多種型別的業務主機,開發者可以選擇合適的主機來託管應用服務。

使用web主機構建微服務應用

使用web主機構建的silky應用具有如下特性:

  1. 提供http服務和RPC服務,暴露http埠和RPC埠
  2. 可以作為外部流量的入口,叢集外部通過http服務訪問微服務應用叢集
  3. 作為RPC服務提供者,通過RPC框架與其他微服務進行通訊

一般地,如果我們希望該服務應用既可以作為RPC服務提供者,也希望外部能夠直接通過http協議訪問應用,那麼我們就可以通過web主機構建微服務應用。這樣的方式適用於將微服務應用拆分給不同的團隊進行開發,開發者也無需要額外的構建閘道器,就可以訪問微服務應用服務。

使用web主機構建Silky微服務應用只需要開發者安裝Silky.Agent.Host包後,在Main()方法中通過Host提供的APIConfigureSilkyWebHostDefaults即可。開發者需要指定Startup類,在Startup中註冊服務和配置http中介軟體。

namespace Silky.Sample
{
    using Microsoft.Extensions.Hosting;
    using System.Threading.Tasks;
    class Program
    {
        public static async Task Main(string[] args)
        {
            await CreateHostBuilder(args).Build().RunAsync();
        }

        private static IHostBuilder CreateHostBuilder(string[] args)
        {
            return Host.CreateDefaultBuilder(args)
                    .ConfigureSilkyWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>());
               
        }
    }
}

當然,我們也可以在構建主機的時候,另外指定啟動模組:

namespace Silky.Sample
{
    using Microsoft.Extensions.Hosting;
    using System.Threading.Tasks;
    class Program
    {
        public static async Task Main(string[] args)
        {
            await CreateHostBuilder(args).Build().RunAsync();
        }

        private static IHostBuilder CreateHostBuilder(string[] args)
        {
            return Host.CreateDefaultBuilder(args)
                    .ConfigureSilkyWebHost<DemoModule>(webBuilder => webBuilder.UseStartup<Startup>());
               
        }
    }
}

自定義的啟動模組DemoModule需要繼承WebHostModule,開發者可以在自定義的啟動模組中,定義應用啟動和停止需要執行的業務方法和配置服務註冊,也可以依賴開發者擴充套件的自定義模組。

    // 依賴開發者自定義的模組
    // [DependsOn(typeof("UserDefinedModule"))]
    public class DemoModule : WebHostModule
    {
        public override Task Initialize(ApplicationContext applicationContext)
        {
            // 開發者可以定義應用程式啟動時執行的業務方法
            return Task.CompletedTask;
        }

        public override Task Shutdown(ApplicationContext applicationContext)
        {
            // 開發者可以定義應用程式停止時執行的業務方法
            return Task.CompletedTask;d
        }

        public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
        {
            // 開發者可以配置服務註冊,作用與Startup類ConfigureServices一致
            
        }

        protected override void RegisterServices(ContainerBuilder builder)
        {
            // 開發者可以通過 Autofac 的ContainerBuilder註冊服務,
            // 例如: IServiceCollection無法註冊命名服務,ContainerBuilder支援註冊命名服務
        }
    }

在啟動類Startup類中配置服務註冊和中介軟體:

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

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services) 
        {
            services
                .AddSilkyHttpCore()
                .AddResponseCaching()
                .AddHttpContextAccessor()
                .AddRouting()
                .AddSilkyIdentity()
                .AddSilkyMiniProfiler()
                .AddSwaggerDocuments();
            
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseSwaggerDocuments();
                app.UseMiniProfiler();
            }
            app.UseRouting();
            app.UseResponseCaching();
            app.UseSilkyWebSocketsProxy();
            app.UseSilkyIdentity();
            app.UseSilkyHttpServer();           
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapSilkyRpcServices();
            });
        }
    }

這樣,我們就可以得到一個既可以提供http服務,也作為rpc服務提供者的應用。

使用通用主機構建微服務應用

使用通用主機構建的silky應用具有如下特性:

  1. 只提供RPC服務,不提供http服務,微服務叢集外部無法直接訪問應用
  2. 可以通過閘道器或是具有http服務的應用間接的訪問該微服務提供的服務

一般地,如果只是作為普通的業務應用,只需要作為RPC服務提供者,服務內部通過RPC框架進行通訊,並不需要對外提供http服務,在這樣的情況下,我們考慮使用通用主機構建微服務應用。

開發者在安裝Silky.Agent.Host包後,在Main()方法中通過Host提供的APIConfigureSilkyGeneralHostDefaults即可通過通用主機構建silky微服務應用。

namespace Silky.Sample
{
    using Microsoft.Extensions.Hosting;
    using System.Threading.Tasks;
    class Program
    {
        public static async Task Main(string[] args)
        {
            await CreateHostBuilder(args).Build().RunAsync();
        }

        private static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureSilkyGeneralHostDefaults();
    }
}

同樣地,我們也可以在構建主機的時候,另外指定啟動模組:

namespace Silky.Sample
{
    using Microsoft.Extensions.Hosting;
    using System.Threading.Tasks;
    class Program
    {
        public static async Task Main(string[] args)
        {
            await CreateHostBuilder(args).Build().RunAsync();
        }

        private static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureSilkyGeneralHost<DemoModule>();
    }
}

在這裡,我們需要自定義的啟動模組DemoModule需要繼承GeneralHostModule,開發者可以在自定義的啟動模組中,定義應用啟動和停止需要執行的業務方法和配置服務註冊,也可以依賴開發者擴充套件的自定義模組。

  // [DependsOn(typeof("UserDefinedModule"))]
    public class DemoModule : GeneralHostModule
    {
        public override Task Initialize(ApplicationContext applicationContext)
        {
            // 開發者可以定義應用程式啟動時執行的業務方法
            return Task.CompletedTask;
        }

        public override Task Shutdown(ApplicationContext applicationContext)
        {
            // 開發者可以定義應用程式停止時執行的業務方法
            return Task.CompletedTask;
        }

        public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
        {
            // 開發者可以配置服務註冊,作用與Startup類ConfigureServices一致
            
        }

        protected override void RegisterServices(ContainerBuilder builder)
        {
            // 開發者可以通過 Autofac 的ContainerBuilder註冊服務,
            // 例如: IServiceCollection無法註冊命名服務,ContainerBuilder支援註冊命名服務
        }
    }

::: warning 注意

與web主機構建微服務應用自定義啟動模組繼承的基類不同,但是作用和使用上一致

:::

通用主機構建的微服務應用,不提供HTTP服務,所有也無需(也沒有必要)配置http中介軟體。但是,開發者可以通過繼承IConfigureService來配置服務的註冊,從而自身服務註冊,或是引入第三方元件。

    public class ConfigureService : IConfigureService
    {
        public void ConfigureServices(IServiceCollection services, IConfiguration configuration)
        {
            services.AddSilkyCaching()
                .AddSilkySkyApm()
                .AddMessagePackCodec();
             
            services.AddDatabaseAccessor(
                options => { options.AddDbPool<DefaultContext>(); },
                "Demo.Database.Migrations");

             // 可以通過服務註冊引入第三方元件,例如:CAP,MassTransit等
        }
    }

構建具有websocket能力的微服務應用

具有websocket服務能力的微服務應用除了能夠提供RPC服務,還可以提供websocket服務。

  1. 提供RPC服務,也提供WebSocket服務
  2. 可以通過閘道器的websocket代理中介軟體與該微服務的websocket服務進行握手

開發者在安裝Silky.Agent.Host包後,在Main()方法中通過Host提供的APIConfigureSilkyGeneralHostDefaults即可通過通用主機構建支援websocket服務的微服務應用。

namespace Silky.Sample
{
    using Microsoft.Extensions.Hosting;
    using System.Threading.Tasks;
    class Program
    {
        public static async Task Main(string[] args)
        {
            await CreateHostBuilder(args).Build().RunAsync();
        }

        private static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureSilkyWebSocketDefaults();
    }
}

同樣地,我們也可以在構建主機的時候,另外指定啟動模組:

namespace Silky.Sample
{
    using Microsoft.Extensions.Hosting;
    using System.Threading.Tasks;
    class Program
    {
        public static async Task Main(string[] args)
        {
            await CreateHostBuilder(args).Build().RunAsync();
        }

        private static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureSilkyWebSocket<DemoModule>();
    }
}

在這裡,我們需要自定義的啟動模組DemoModule需要繼承WebSocketHostModule,開發者可以在自定義的啟動模組中,定義應用啟動和停止需要執行的業務方法和配置服務註冊,也可以依賴開發者擴充套件的自定義模組。

// [DependsOn(typeof("UserDefinedModule"))]
    public class DemoModule : WebSocketHostModule
    {
        public override Task Initialize(ApplicationContext applicationContext)
        {
            // 開發者可以定義應用程式啟動時執行的業務方法
            return Task.CompletedTask;
        }

        public override Task Shutdown(ApplicationContext applicationContext)
        {
            // 開發者可以定義應用程式停止時執行的業務方法
            return Task.CompletedTask;
        }

        public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
        {
            // 開發者可以配置服務註冊,作用與Startup類ConfigureServices一致
            
        }

        protected override void RegisterServices(ContainerBuilder builder)
        {
            // 開發者可以通過 Autofac 的ContainerBuilder註冊服務,
            // 例如: IServiceCollection無法註冊命名服務,ContainerBuilder支援註冊命名服務
        }
    }

::: warning 注意

與web主機構建微服務應用自定義啟動模組繼承的基類不同,但是作用和使用上一致

:::

構建具有websocket能力的服務,實現應用服務介面的類需要繼承WsAppServiceBase。在與前端建立會話後,就可以通過SessionManager向前端傳送訊息。

    public class TestAppService : WsAppServiceBase, ITestAppService
    {
        private readonly ILogger<TestAppService> _logger;

        public TestAppService(ILogger<TestAppService> logger)
        {
            _logger = logger;
        }

        protected override void OnOpen()
        {
            base.OnOpen();
            _logger.LogInformation("websocket established a session");
            
        }

        protected override void OnMessage(MessageEventArgs e)
        {
            _logger.LogInformation(e.Data);
        }

        protected override void OnClose(CloseEventArgs e)
        {
            base.OnClose(e);
            _logger.LogInformation("websocket disconnected");
        }
    }

前端需要通過閘道器的websocket代理中介軟體,與具體的websocket服務例項建立會話時,需要滿足如下要求:

  1. 需要通過請求頭或是qString引數指定bussinessId,通過該值使用雜湊演算法,路由到具體的websocket服務例項。
  2. 為保證每次都能夠路由到同一個websocket服務例項,websocket服務對應的閘道器例項只能有一個。
  3. 該閘道器必須要引用websocket服務代理中介軟體。
// 需要在閘道器的Configure()配置websocket代理中介軟體
app.UseSilkyWebSocketsProxy();

::: warning 注意

  1. 開發者可以考慮,普通業務服務對應一組閘道器應用(支援部署多個例項),websocket應用對應一組閘道器應用(只允許一個服務例項)

:::

構建閘道器

這裡,閘道器的作用只是作為叢集流量的入口,將http請求轉發到叢集內部,交個各個微服務應用的服務進行處理,並不作為rpc服務提供者。也就是說,這裡構建的閘道器只能作為服務消費者。

  1. 只提供http服務,作為叢集流量入口
  2. 不提供RPC服務,不可以作為rpc服務提供者

::: warning 注意

閘道器與web主機構建業務主機的區別在於,閘道器只能作為服務消費者,轉發外部的http請求,而後者除了具有轉發http請求的能力之外,還能作為RPC服務提供者。

:::

開發者在安裝Silky.Agent.Host包後,在Main()方法中通過Host提供的APIConfigureSilkyGatewayDefaults即可通過通用主機構建支援websocket服務的微服務應用。

namespace Silky.Sample
{
    using Microsoft.Extensions.Hosting;
    using System.Threading.Tasks;
    class Program
    {
        public static async Task Main(string[] args)
        {
            await CreateHostBuilder(args).Build().RunAsync();
        }

    private static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureSilkyGatewayDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
    }
}

當然,也可以自定義啟動模組,只需要將自定義的啟動模組DemoModule繼承的基類修改為GatewayHostModule:

namespace Silky.Sample
{
    using Microsoft.Extensions.Hosting;
    using System.Threading.Tasks;
    class Program
    {
        public static async Task Main(string[] args)
        {
            await CreateHostBuilder(args).Build().RunAsync();
        }

    private static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureSilkyGateway<DemoModule>(webBuilder => { webBuilder.UseStartup<Startup>(); });
    }
}

開源地址

線上文件

相關文章