Consul之服務注冊
前言
在分布式架構中,服務治理是必須面對的問題,如果缺乏簡單有效治理方案,各服務之間只能通過人肉配置的方式進行服務關系管理,當遇到服務關系變化時,就會變得極其麻煩且容易出錯。
Consul 是一個用來實現分布式系統服務發現與配置的開源工具。
環境:Win10 +VS2022 +.NET5.0 + Consul 1.6.1.1
1 Consul簡介
Consul內置了服務注冊與發現框架、分布一致性協議實現、健康檢查、Key/Value存儲、多數據中心方案,不再需要依賴其他工具(比如 ZooKeeper 等),使用起來也較為簡單。由 HashiCorp 公司用 Go 語言開發。
地址:https://www.consul.io/
Consul的下載:
https://www.consul.io/downloads.html
2 Consul 架構
Consul 集群支持多數據中心。在單個數據中心中,Consul 分為 Client 和 Server 兩種節點(所有的節點也被稱為 Agent),Server 節點保存數據,Client 負責健康檢查及轉發數據請求到 Server,本身不保存注冊信息;Server 節點有一個 Leader 和多個 Follower,Leader 節點會將數據同步到 Follower,Server 節點的數量推薦是3個或者5個,在 Leader 掛掉的時候會啟動選舉機制產生一個新 Leader。
下面這張圖來源於Consul官網,很好的解釋了Consul的工作原理,先大致看一下。
3 Consul 集群搭建
這里使用 Docker 搭建 3個 Server 節點 + 1 個 Client 節點,API 服務通過 Client 節點進行服務注冊和發現。
從 Docker Hub 拉取 Consul 鏡像
docker pull consul |
啟動4個Consul Agent,3個Server(會選舉出一個leader),1個Client。
#啟動第1個Server節點,集群要求要有3個Server,將容器8500端口映射到主機8900端口,同時開啟管理界面 docker run -d --name=consul1 -p 8900:8500 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=true --bootstrap-expect=3 --client=0.0.0.0 -ui
#啟動第2個Server節點,並加入集群 docker run -d --name=consul2 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=true --client=0.0.0.0 --join 172.17.0.2
#啟動第3個Server節點,並加入集群 docker run -d --name=consul3 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=true --client=0.0.0.0 --join 172.17.0.2
#啟動第4個Client節點,並加入集群 docker run -d --name=consul4 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=false --client=0.0.0.0 --join 172.17.0.2 |
查看節點狀態和類型
docker exec -t cs1 consul members |
當前為3 個 Server 類型節點 ,1 個 Client 類型節點。
查看 Server 節點類型
docker exec -t cs1 consul operator raft list-peers
|
第1個啟動容器的IP一般是172.17.0.2,后邊啟動的幾個容器IP會排着來:172.17.0.3、172.17.0.4、172.17.0.5。
這些Consul節點在Docker的容器內是互通的,他們通過橋接的模式通信。但是如果主機要訪問容器內的網絡,需要做端口映射。在啟動第一個容器時,將Consul的8500端口映射到了主機的8900端口,這樣就可以方便的通過主機的瀏覽器查看集群信息。
輸入exit可以跳出容器。
進入容器consul1:
docker exec -it consul1 /bin/sh #執行ls后可以看到consul就在根目錄ls
|
4 項目實現
4.1 新建WebAPI服務項目
新建一個WebAPI接口,命名為“Yak.Ocelot.Api”,修改啟動端口為“6000”。
"Yak.Ocelot.Api": { "commandName": "Project", "dotnetRunMessages": "true", "launchBrowser": true, "launchUrl": "weatherforecast", "applicationUrl": "http://localhost:6000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } |
4.2 添加Consul依賴
添加Consul依賴后,Yak.Ocelot.Api.csproj項目文件下添加了下面代碼。
<ItemGroup> <PackageReference Include="Consul" Version="1.6.1.1" /> </ItemGroup> |
4.3 添加健康檢查接口
添加Health控制器,代碼:
[Route("[controller]/[action]")] [ApiController] public class HealthController : ControllerBase { [HttpGet("/healthCheck")] public IActionResult Check() => Ok("ok"); } |
4.4 把服務注冊到Consul
- 項目中添加Consul 注冊發現相關參數類ConsulOption。
/// <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; } } |
- 添加Consul注冊發現擴展類ConsulBuilderExtensions。
public static class ConsulBuilderExtensions { public static IApplicationBuilder RegisterConsul(this IApplicationBuilder app, IHostApplicationLifetime lifetime, ConsulOption consulOption) { var consulClient = new ConsulClient(x => { 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; } } |
- 添加Consul配置,修改appsettings.json文件。
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*", "Consul": { "ServiceName": "service-a", "ServiceIP": "127.0.0.1", "ServicePort": 6000, "ServiceHealthCheck": "http://192.168.142.1:6000/healthCheck", "Address": "http://127.0.0.1:8500" } } |
- 修改Startup。
public void ConfigureServices(IServiceCollection services) { services.AddSingleton(Configuration.GetSection("Consul").Get<ConsulOption>()); services.AddControllers(); }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime lifetime, ConsulOption consulOption) { ......... // 注冊 app.RegisterConsul(lifetime, consulOption); ........... } |
4.5 啟動Consul
這里是Win10系統,下載相應的Consul后,在文件夾下創建啟動BAT文件用於啟動Consul,雙擊啟動。
瀏覽器中輸入:http://localhost:8500/
BAT文件:
consul agent -dev |
4.6 服務發現
啟動項目,查看到服務已經注冊到Consul中。
5 總結
通過這節我們學習了Consul及怎樣把服務注冊到Consul中,下節中介紹結合Ocelot發現服務,訪問服務。
6 鳴謝
https://www.cnblogs.com/bossma/p/9756809.html
https://www.cnblogs.com/edisonchou/p/9124985.html
7 源碼
https://github.com/yandaniugithub/Yak.Ocelot.Demo.git