概念
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: https://github.com/liuhll/lms
gitee: https://gitee.com/liuhll2/lms