.netcore consul實現服務註冊與發現-集群完整版
一、Consul的集群介紹
? ?Consul Agent有兩種運行模式:Server和Client。這裏的Server和Client只是Consul集群層面的區分,與搭建在Cluster之上的應用服務無關, 以Server模式運行的Consul Agent節點用於維護Consul集群的狀態,官方建議每個Consul Cluster至少有3個或以上的運行在Server Mode的Agent,Client節點不限。
1、Server節點需要三臺或以上機器
2、Client節點不限
二、Consul環境準備
準備了三臺Linux(CentOS)虛擬機(Consul Server)二臺Linux(CentOS)虛擬機(Consul Client)
Consul Server服務IP分別為:
192.168.31.175
192.168.31.176
192.168.31.177
Consul?Client服務IP分別為:
192.168.31.178
192.168.31.179
?
其中,192.168.31.175會作為leader角色,其余兩臺192.168.31.176和192.168.31.177會作為follower角色。當然,實際環境中leader角色不會是一個固定的,會隨著環境的變化(比如Leader宕機或失聯)由算法選出新的leader。在進行下面的操作會前,請確保三臺節點能夠相互ping通,並能夠和宿主機也ping通。另外,192.168.31.178和192.168.31.179會作為client角色,並且和其余三臺虛擬機互相ping通。
三、Consul正式安裝
可以參考上一篇文章的安裝方法:.netcore consul實現服務註冊與發現-單臺節點
一定保證以上五臺安裝成功
1、測試Consul是否安裝成功
> consul
如下圖表示成功:
2、Consul Server服務端安裝(啟動與配置Consul服務)
服務端192.168.31.175執行
> consul agent -server -ui -bootstrap-expect=3 -data-dir=/tmp/consul -node=consul-175 -client=0.0.0.0 -bind=192.168.31.175 -datacenter=dc1
服務端192.168.31.176執行
> consul agent -server -ui -bootstrap-expect=3 -data-dir=/tmp/consul -node=consul-176 -client=0.0.0.0 -bind=192.168.31.176 -datacenter=dc1 -join 192.168.31.175
服務端192.168.31.177執行
> consul agent -server -ui -bootstrap-expect=3 -data-dir=/tmp/consul -node=consul-177 -client=0.0.0.0 -bind=192.168.31.177 -datacenter=dc1 -join 192.168.31.175
註:因為是集群安裝,bootstrap-expect=3,以服務端的數量為準
?? ?? ?datacenter=dc1,三臺必須在一個數據中心
?
?? ???176和177的啟動命令中,有一句 -join 192.168.31.175 => 有了這一句,就把176和177加入到了175所在的集群中。
啟動之後,集群就開始了Vote(投票選Leader)的過程
?
命令:查看各個server的情況:
> consul members
命令:查看目前全部的consul的角色狀態:
> consul operator raft list-peers
?
3、通過UI查看集群狀態
Consul不僅提供了豐富的命令查看集群情況,還提供了一個WebUI,默認端口8500,我們可以通過訪問這個URL(eg. http://192.168.31.175:8500)得到如下圖所示的WebUI:
4、模擬Leader掛掉,查看Consul集群的新選舉Leader
直接停止192.168.31.175的服務,或者暴力直接關機
輸入命令查看服務狀態
> consul members
查看其余兩個節點的日誌或者命令可以發現,consul-176被選為了新的leader
我們也可以在次通過UI界面來查看狀態:
雖然這裏192.168.31.175這個原leader節點掛掉了,但是只要超過一半的Server(這裏是2/3還活著)還活著,集群是可以正常工作的,這也是為什麽像Consul、ZooKeeper這樣的分布式管理組件推薦我們使用3個或5個節點來部署的原因。
?
註:以上也可以將.netcore項目部署在Consul Server上,但官方建議用Consul Client來關聯,分別做各自的事情,互不影響。
?
5、Consul Client安裝
為了節約虛擬機,目前在192.168.31.178部署.netcore項目
> mkdir /data/mvc
> mkdir /data/api
> cd /data/mvc/
> dotnet new mvc
> cd /data/api/
> dotnet new webapi
>dotnet run
啟動並運行mvc,webapi兩個項目,保證能正常訪問,如圖正常訪問
6、將.netcore服務註冊到Consul(通過配置文件來註冊服務)
vi /etc/consul/services_config.json
{
"services":[
{
"id": "CLIENT_SERVICE_01",
"name" : "MVCClientService",
"tags": [
"urlprefix-/MVCClientService01"
],
"address": "192.168.31.178",
"port": 5000,
"checks": [
{
"name": "clientservice_check",
"http": "http://192.168.31.178:5000",
"interval": "10s",
"timeout": "5s"
}
]
},
{
"id": "CLIENT_SERVICE_02",
"name" : "APIClientService",
"tags": [
"urlprefix-/APIClientService02"
],
"address": "192.168.31.178",
"port": 5000,
"checks": [
{
"name": "clientservice_check",
"http": "http://192.168.31.178/api/values",
"interval": "10s",
"timeout": "5s"
}
]
}
]
}
在Consul Client 192.168.31.178運行命令:
consul agent -config-dir=/etc/consul -data-dir=/tmp/consul -node=consul-178 -client=0.0.0.0 -bind=192.168.31.178 -datacenter=dc1 -join 192.168.31.175
如下圖表示正常啟動,並將192.168.31.178加入到服務集群192.168.31.175中
7、查看Consul集群狀態
可以看到192.168.31.178加入到了集群中,表示正常,還能看到.netcore的兩個服務哦,也表示正常
Consul不僅僅提供了服務註冊,還提供了服務發現,我們可以通過調用其提供的API來發現服務的IP和Port。
8、通過consul api 接口註冊服務
-
創建一個ASP.NET Core WebAPI程序
?? ??? ??? ?
-
創建一個HealthController用於Consul的健康檢查? ??
[Produces("application/json")]
[Route("api/Health")]
public class HealthController : Controller
{
[HttpGet]
public IActionResult Get() => Ok("ok");
}
註:Consul會通過call這個API來確認Service的健康狀態。
?
-
基於IApplicationBuilder寫一個擴展方法,用於調用Consul API
-
在nuge管理器中引入Consul包
?
public static class ConsulBuilderExtensions
{
// 服務註冊
public static IApplicationBuilder RegisterConsul(this IApplicationBuilder app, IApplicationLifetime lifetime, HealthService healthService, ConsulService consulService)
{
var consulClient = new ConsulClient(x => x.Address = new Uri($"http://{consulService.IP}:{consulService.Port}"));//請求註冊的 Consul 地址
var httpCheck = new AgentServiceCheck()
{
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服務啟動多久後註冊
Interval = TimeSpan.FromSeconds(10),//健康檢查時間間隔,或者稱為心跳間隔
HTTP = $"http://{healthService.IP}:{healthService.Port}/api/health",//健康檢查地址
Timeout = TimeSpan.FromSeconds(5)
};
// Register service with consul
var registration = new AgentServiceRegistration()
{
Checks = new[] { httpCheck },
ID = healthService.Name + "_" + healthService.Port,
Name = healthService.Name,
Address = healthService.IP,
Port = healthService.Port,
Tags = new[] { $"urlprefix-/{healthService.Name}" }//添加 urlprefix-/servicename 格式的 tag 標簽,以便 Fabio 識別
};
consulClient.Agent.ServiceRegister(registration).Wait();//服務啟動時註冊,內部實現其實就是使用 Consul API 進行註冊(HttpClient發起)
lifetime.ApplicationStopping.Register(() =>
{
consulClient.Agent.ServiceDeregister(registration.ID).Wait();//服務停止時取消註冊
});
return app;
}
}
-
在Starup類的Configure方法中,調用此擴展方法
#region register this service
ConsulService consulService = new ConsulService()
{
IP = Configuration["Consul:IP"],
Port = Convert.ToInt32(Configuration["Consul:Port"])
};
HealthService healthService = new HealthService()
{
IP = Configuration["Service:IP"],
Port = Convert.ToInt32(Configuration["Service:Port"]),
Name = Configuration["Service:Name"],
};
app.RegisterConsul(lifetime, healthService, consulService);
#endregion
?
-
其中用到了appSettings.json配置文件,其定義如下:
"Service": {
"Name": "DMSWebAPITest",
"IP": "localhost",
"Port": "5001"
},
"Consul": {
"IP": "localhost",
"Port": "8500"
}
?
-
其中ConsulService類定義如下:
public class ConsulService
{
public string IP { get; set; }
public int Port { get; set; }
}
-
其中HealthService類定義如下:
?
public class HealthService
{
public string Name { get; set; }
public string IP { get; set; }
public int Port { get; set; }
}
?
-
確保HealthController的API能正常訪問,以便做健康檢查
-
成功運行後,查看Consul集群的狀態,UI界面
?
Exceptionless作分布式日誌開源框架,Log4net,NLog,Autofac屬性註入,Consul API接口服務註冊實例等開源地址:https://github.com/hailang2ll/DMS
?
實戰中參考的資料:https://www.cnblogs.com/edisonchou/p/9124985.html
?
交流qq群:18362376
?
.netcore consul實現服務註冊與發現-集群完整版