.net core Ocelot+consul實現閘道器及服務註冊和服務發現
Ocelot是一個用.NET Core實現並且開源的API閘道器。對於閘道器概念不是很清楚的可以參照https://www.jianshu.com/p/7baab672b822,這位大佬講到感覺滿到位哈。
Consul 是 HashiCorp 公司的一個用於實現分散式系統的服務發現與配置工具。Consul內建了服務註冊與發現框 架、分佈一致性協議實現、健康檢查、Key/Value儲存、多資料中心方案。
這篇文章將一步一步介紹如何使用Ocelot+consul實現閘道器及服務註冊和服務發現功能。
一、我們使用.net core 新建一個閘道器專案和兩個webApi專案。建好後的專案結構如下圖。
二、ApiGateway是閘道器專案,新增Ocelot和consul包,為了在Ocelot中使用Consul來實現服務發現,這裡需要使用Ocelot提供Consul支援的NuGet包。具體的依賴包如下圖。
ConfigureServices新增Ocelot和Consul的注入,AddJsonFile("ocelot.json")指定了ocelot的配置檔案。
public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddOcelot(new ConfigurationBuilder() .AddJsonFile("ocelot.json") .Build()).AddConsul(); }
Configure方法中新增ocelot中介軟體。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseOcelot(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints=> { endpoints.MapControllers(); }); }
新增ocelot.json配置檔案,可以配置服務發現、路由、負載均很、鑑權、熔斷限流等。這裡只演示路由和服務發現功能,如下圖。
Routes配置路由資訊,"UseServiceDiscovery": true,表示使用服務發現功能,
"DownstreamPathTemplate": "/{url}",
"DownstreamScheme": "http",
指定了下游的url及使用的通訊協議,{url}是通配的意思。
"ServiceName": "ServiceA",指定下游使用的服務名是什麼,使用這個服務名到consul伺服器去找到下游對應的IP及埠。
"UpstreamPathTemplate": "/ServiceA/{url}",
"UpstreamHttpMethod": [ "Get" ]
指定了上游的訪問路由格式及請求方式。
"GlobalConfiguration": {
"BaseUrl": "https://192.168.0.103:5000",
"ServiceDiscoveryProvider": {
"Host": "192.168.0.101",
"Port": 8500,
"Type": "Consul"
}
}
這段是全域性配置,BaseUrl表示ocelot上游使用的IP及埠。ServiceDiscoveryProvider指定Consul的伺服器和埠,用於服務發現。至此,api閘道器部分已經完成。
三、webapi配置
為ServiceA和ServiceB分別新增consul的nuget包。
然後在appsettings.json中配置consul伺服器的配置資訊。如下圖
這裡需要注意ServiceName,在Ocelot中使用的服務發現名也就是這個名字,也就是說,服務需要先到Consul上註冊,然後才能發現。
接著我們新增兩個檔案ConsulBuilderExtensions.cs和ConsulOption.cs用於註冊Consul.
public static class ConsulBuilderExtensions { public static IApplicationBuilder RegisterConsul(this IApplicationBuilder app, IApplicationLifetime lifetime, ConsulOption consulOption) { var consulClient = new ConsulClient(x => { // consul 服務地址 x.Address = new Uri(consulOption.Address); }); var registration = new AgentServiceRegistration() { ID = Guid.NewGuid().ToString(), Name = consulOption.ServiceName,// 服務名 Address = consulOption.ServiceIP, // 服務繫結IP Port = consulOption.ServicePort, // 服務繫結埠 Check = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服務啟動多久後註冊 Interval = TimeSpan.FromSeconds(10),//健康檢查時間間隔 HTTP = consulOption.ServiceHealthCheck,//健康檢查地址 Timeout = TimeSpan.FromSeconds(5) } }; // 服務註冊 consulClient.Agent.ServiceRegister(registration).Wait(); // 應用程式終止時,服務取消註冊 lifetime.ApplicationStopping.Register(() => { consulClient.Agent.ServiceDeregister(registration.ID).Wait(); }); return app; } }
/// <summary> /// Consul 註冊發現相關引數 /// </summary> public class ConsulOption { /// <summary> /// 服務名稱 /// </summary> public string ServiceName { get; set; } /// <summary> /// 服務IP /// </summary> public string ServiceIP { get; set; } /// <summary> /// 服務埠 /// </summary> public int ServicePort { get; set; } /// <summary> /// 服務健康檢查地址 /// </summary> public string ServiceHealthCheck { get; set; } /// <summary> /// Consul 地址 /// </summary> public string Address { get; set; } }
然後在startup.cs中使用consul中介軟體
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApplicationLifetime lifetime) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseAuthorization(); var consulOption = new ConsulOption { ServiceName = Configuration["ServiceName"], ServiceIP = Configuration["ServiceIP"], ServicePort = Convert.ToInt32(Configuration["ServicePort"]), ServiceHealthCheck = Configuration["ServiceHealthCheck"], Address = Configuration["ConsulAddress"] }; app.RegisterConsul(lifetime, consulOption); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }