Ocelot是一個用.NET Core實現並且開源的API網關。對於網關概念不是很清楚的可以參照https://www.jianshu.com/p/7baab672b822。
Consul 是 HashiCorp 公司的一個用於實現分布式系統的服務發現與配置工具。Consul內置了服務注冊與發現框 架、分布一致性協議實現、健康檢查、Key/Value存儲、多數據中心方案。
這篇文章將一步一步介紹如何使用Ocelot+consul實現網關及服務注冊和服務發現功能。
一、安裝Consul,安裝后的效果如下圖。
二、建立項目。
使用.net core 新建三個webAPI項目,分別為網關、服務A和服務B,建好后的項目結構如下圖
三、網關配置
ApiGateway是網關項目,為其添加Ocelot和consul包,具體的依賴包如下圖。
然后在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",指定下游使用的服務名是ServiceA,使用ServiceA這個服務名到consul服務器去發現下游對應的IP及端口。
"UpstreamPathTemplate": "/ServiceA/{url}",
"UpstreamHttpMethod": [ "Get" ]
指定了上游的訪問路由格式及請求方式。
"GlobalConfiguration": {
"BaseUrl": "https://192.168.0.103:5000",
"ServiceDiscoveryProvider": {
"Host": "192.168.0.102",
"Port": 8500,
"Type": "Consul"
}
}
這段是全局配置,BaseUrl表示ocelot上游使用的IP及端口。ServiceDiscoveryProvider指定Consul的服務器和端口,用於服務發現。至此,api網關部分已經完成。
四、webapi配置
為ServiceA和ServiceB分別添加consul的nuget包。
然后在appsettings.json中配置consul服務器的配置信息。如下圖
這里需要注意ServiceName,在Ocelot中使用的服務發現名也就是ServiceA這個名字,也就是說,服務需要先到Consul上注冊,然后才能發現。
添加健康檢查接口
[Route("[controller]/[action]")] [ApiController] public class HealthController : ControllerBase { [HttpGet("/healthCheck")] public IActionResult Check() => Ok("ok"); }
接着我們添加兩個文件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(); }); }
至此大功告成,我們看一下效果。將三個項目均設置為啟動項目,並啟動。
consul服務器看到了注冊到的ServiceA和ServiceB
如下圖,訪問Ocelot上游路由地址http://192.168.0.103:5000/ServiceA/weatherforecast和http://192.168.0.103:5000/ServiceB/weatherforecast,可以正確訪問到服務A和服務B。路由及服務注冊、服務發現均已實現。
源代碼地址:https://gitee.com/lp244392323/LP.Demo/tree/master/OcelotWithConsul/WebAppOcelotWithConsul