主機的概念
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應用具有如下特性:
- 提供http服務和RPC服務,暴露http埠和RPC埠
- 可以作為外部流量的入口,叢集外部通過http服務訪問微服務應用叢集
- 作為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應用具有如下特性:
- 只提供RPC服務,不提供http服務,微服務叢集外部無法直接訪問應用
- 可以通過閘道器或是具有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服務。
- 提供RPC服務,也提供WebSocket服務
- 可以通過閘道器的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服務例項建立會話時,需要滿足如下要求:
- 需要通過請求頭或是
qString
引數指定bussinessId
,通過該值使用雜湊演算法,路由到具體的websocket服務例項。 - 為保證每次都能夠路由到同一個websocket服務例項,websocket服務對應的閘道器例項只能有一個。
- 該閘道器必須要引用websocket服務代理中介軟體。
// 需要在閘道器的Configure()配置websocket代理中介軟體
app.UseSilkyWebSocketsProxy();
::: warning 注意
- 開發者可以考慮,普通業務服務對應一組閘道器應用(支援部署多個例項),websocket應用對應一組閘道器應用(只允許一個服務例項)
:::
構建閘道器
這裡,閘道器的作用只是作為叢集流量的入口,將http請求轉發到叢集內部,交個各個微服務應用的服務進行處理,並不作為rpc服務提供者。也就是說,這裡構建的閘道器只能作為服務消費者。
- 只提供http服務,作為叢集流量入口
- 不提供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>(); });
}
}
開源地址
- github: https://github.com/liuhll/silky
- gitee: https://gitee.com/liuhll2/silky