lms微服務框架主機介紹
概念
lms的主機與.net的主機概念一致。是封裝應用資源的對象,用於託管應用和管理應用的生命周期。
一般地,Lms會使用到.net兩種類型的主機。
.net的通用主機
如果用於託管普通的業務應用,該微服務模塊本身並不需要對直接對集群外部提供訪問入口。那麼,您可以使用.net的通用主機註冊lms服務框架。.net的通用主機無法提供http請求,也無法配置http的請求管道(即:中間件)。
但是在註冊lms框架後,lms框架會註冊dotnetty的服務監聽者,並會暴露rpc端口號。但是由於lms框架的安全機制,集群外部並不允許通過tcp
協議通過rpc端口號直接訪問該微服務模塊的應用接口。
.net的web主機
如果您需要訪問該服務模塊的應用接口,您必須要通過.net的web主機註冊lms框架,並配置lms框架的請求管道。這樣,web構建的主機通過引用某個微服務的應用接口項目(包),通過應用接口的代理與微服務集群內部實現rpc通信。
lms的業務主機類型
用於託管業務應用的普通主機
一般地,用於託管普通應用的主機,我們使用.net的通用主機即可,該類型的主機不提供http請求服務,所以也不支持配置請求管道(中間件)。
為什麼lms使用.net通用主機託管普通業務應用?
對一個微服務集群應用來說,一般地,服務之間的內部通信我們通過dotnetty通信框架實現的rpc協議通過rpc端口號進行通信。同時,我們集群內部rpc通信過程中,服務消費者在調用時,指定rpc的token
,服務消費者通過驗證給定的rpc token
是否一致,從而保證通信的合法性。rpc通信也限制了token
的設置只能在內部rpc通信時進行設置,這樣,集群外部也無法通過rpc端口與普通業務微服務主機進行通信。
另外一方面,微服務想要對外暴露訪問入口,我們只需要通過網關引用微服務模塊的應用接口層(包),通過應用接口生成的代理,與微服務主機實例進行rpc通信就可以了。通過這種設計,有效的保證了微服務集群內部的安全性,也方便的微服務集群的統一認證與授權。微服務集群的統一認證和授權,我們只需要在訪問入口(網關)統一處理即可。
創建一個用於託管普通應用的主機非常簡單。
1. 創建一個應用台程序
2. 安裝Silky.Lms.NormHost
包
3. 註冊LMS服務
通過Host.CreateDefaultBuilder()
創建IHostBuilder
對象後,調用RegisterLmsServices<TModuel>
註冊Lms服務框架即可。其中,TModuel
是您指定的啟動模塊。啟動模塊指定了您要依賴的lms模塊。Silky.Lms.NormHost
包提供了默認的啟動模塊NormHostModule
。
所以,您只需要通過如下代碼即可獲取到一個支持Lms服務的微服務主機構建者。
private static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
.RegisterLmsServices<NormHostModule>()
;
}
4. 新增主機必要的配置項
lms框架支持通過yml
或是json
格式對框架進行配置。
您可以通過appsettings.yml
為公共配置項指定配置信息,也可以通過新增appsettings.${ENVIRONMENT}.yml
文件為指定的環境配置信息。
對lms普通業務主機來說:
A) (必須的)您必須要配置的是服務註冊中心地址,lms默認使用zookeeper
作為服務註冊中心,支持多服務註冊中心地址。同一個集群的註冊中心地址使用,
分割,不同集群的服務註冊中心地址使用;
分割。
B) (必須的)您必須要配置redis服務作為分佈式鎖服務。
C) (必須的) lms rpc通信token
D) (可選的)您需要為rpc通信服務指定主機地址和端口號。主機地址缺省值為0.0.0.0
,rpc端口號缺省值為:2200
。如果您使用項目的方式(非容器化)進行開發和調式應用的話,那麼您需要為每一個微服務模塊的主機指定一個端口號(端口號不允許重複),如果您使用容器化的方式開發和調式應用的話,那麼,端口號可以使用缺省值(每個應用獨佔一個容器,擁有自己獨立的運行環境),但是主機地址不能夠設置為localhost
或是127.0.0.1
。
E) (可選的)使用redis作為分佈式緩存服務。如果使用redis
作為分佈式緩存服務的話,那麼除了配置緩存服務地址,您還需要將配置項distributedCache.redis.isEnabled
設置為true
。
一個最少的的lms主機配置如下所示:
rpc:
token: ypjdYOzNd4FwENJiEARMLWwK0v7QUHPW
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
lock:
lockRedisConnection: 127.0.0.1:6379,defaultDatabase=1
5. 運行主機
通過IHostBuilder
的實例對象的Build()
方法獲取到主機對象後,調用RunAsync()
方法即可運行主機。
public static async Task Main(string[] args)
{
await CreateHostBuilder(args).Build().RunAsync();
}
5. 託管應用
主機要實現微服務應用的託管,只需要引用應用服務的實現(即:對應用層的引用)即可。在主機啟動時,服務主機會自動解析到應用本身,並將應用服務條目的路由註冊到服務註冊中心,引用了該服務的應用接口層(包)的其他微服務模塊(或網關)也可以訂閱到服務路由的變化。
支持websocket通信的業務主機
Lms框架使用WebSocketSharp實現ws通信協議。
一個業務微服務模塊主機想要支持通過ws
協議通信,需要依賴WebSocketModule
模塊。在主機啟動後,服務主機除了通過rpc端口
與其他微服務模塊進行rpc通信之外,還支持通過ws端口
與透過代理與前端實現ws通信。
支持websocket通信的業務主機與普通業務應用主機的構建過程一致,也是通過.net的泛型主機進行託管應用。不同的地方只是控制台項目安裝的包和指定的啟動項目不一樣。
您只需要在控制台應用中安裝Silky.Lms.WsHost
包。將設置的啟動模塊設置為:WsHostModule
即可。這樣,一個普通的業務應用主機也支持ws協議透過網關的代理與前端進行通信。
private static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
.RegisterLmsServices<WsHostModule>()
;
}
要使得一個應用服務支持與前端的ws
進行會話,那麼這個應用服務必須要繼承基類WsAppServiceBase
。更多關於websocket使用知識請參考ws通信節點。
接受Http請求的web主機
一般地,我們使用.net的web主機來構建網關,通過引用各個業務微服務模塊的應用接口層(包),通過lms中間件,解析到相應的服務條目,並通過應用接口的代理實現與具體的某個業務應用主機實例進行通信,完成業務處理。
創建一個接受http請求的lms web主機非常簡單。
1. 創建一個空的asp.net web應用
2. 安裝Silky.Lms.WebHost
包
3. 註冊LMS服務
註冊lms服務,並指定WebHostModule
作為啟動模塊,並設置Startup
類。
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.RegisterLmsServices<WebHostModule>()
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
4. 在Startup類中設置swagger文檔和啟用lms請求管道
public void ConfigureServices(IServiceCollection services)
{
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo {Title = "Lms Gateway", Version = "v1"});
c.MultipleServiceKey();
var applicationAssemblies = EngineContext.Current.TypeFinder.GetAssemblies()
.Where(p => p.FullName.Contains("Application") || p.FullName.Contains("Domain"));
foreach (var applicationAssembly in applicationAssemblies)
{
var xmlFile = $"{applicationAssembly.GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
if (File.Exists(xmlPath))
{
c.IncludeXmlComments(xmlPath);
}
}
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment() || env.EnvironmentName == "ContainerDev")
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Lms Gateway Demo v1"));
}
app.ConfigureLmsRequestPipeline(); // 啟用lms請求管道
}
在啟用lms請求管道後,會根據您按照的包,自動引用您設置相關中間件。
5. 配置
網關的配置方式與普通業務微服務主機一致,更多配置信息,請參考配置節點。
6. 為其他微服務模塊代理
引用其他微服務應用接口層(包),為其他微服務模塊的應用服務生成代理,通過代理與集群內部的rpc通信。
自定義啟動模塊
在介紹構建lms微服務主機時,我們知道在註冊lms服務的過程中,必須要指定一個啟動模塊。一般地,在構建普通業務微服務主機時,我們指定的啟動模塊是NormHostModule
;構建支持ws協議的微服務主機時,我們指定的啟動模塊是WsHostModule
;構建支持接受Http請求的web主機時,指定的是WebHostModule
。實際上,我們是通過指定的啟動模塊指定lms框架依賴的必要模塊。
如果您想自己指定依賴的模塊(例如:您擴展了一個lms模塊項目,希望依賴它),或是在應用啟動或是停止時,指定相關的操作,那麼您可能就需要自定義啟動模塊。
自定義啟動模塊,可以繼承LmsModule
或是相應的業務微服務的啟動模塊(例如:NormHostModule
)。
如果您繼承的是LmsModule
,那麼您必須要顯式的指定需要依賴的lms模塊。如果您繼承的模塊基類已經指定了模塊的依賴關係(例如:繼承NormHostModule
),那麼基類的模塊依賴關係也會被繼承。
在啟動模塊中,您可以通過重寫Initialize
方法實現應用啟動時的初始化方法,或是重寫Shutdown
實現應用停止時的方法,也可以通過重寫RegisterServices
通過ContainerBuilder
註冊服務的生命周期。
例如:
[DependsOn(typeof(ZookeeperModule),
typeof(DotNettyTcpModule),
typeof(MessagePackModule),
typeof(RpcProxyModule),
typeof(TransactionTccModule),
typeof(AutoMapperModule)
)]
public class DemoStartUpHostModule : LmsModule
{
public async override Task Initialize(ApplicationContext applicationContext)
{
// 應用啟動時執行方法
}
protected override void RegisterServices(ContainerBuilder builder)
{
// 通過ContainerBuilder向ioc容器註冊服務
}
public async override Task Shutdown(ApplicationContext applicationContext)
{
// 應用停止時執行方法
}
}
在構建主機時指定DemoStartUpHostModule
作為啟動模塊。
private static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
.RegisterLmsServices<DemoStartUpHostModule>()
;
}
開源地址
github: //github.com/liuhll/lms
gitee: //gitee.com/liuhll2/lms