Consul在.Net Core中初體驗
簡介
在閱讀本文前我想您應該對微服務架構有一個基本的或者模糊的了解
Consul是一個服務管理軟件,它其實有很多組件,包括服務發現配置共享鍵值對存儲等
本文主要講解Consul的服務註冊服務發現以及集群的配置
參考資料:
https://blog.csdn.net/younger_china/article/details/79462530
https://www.cnblogs.com/shanyou/p/6286207.html
服務發現
假設有服務A,B,C.服務A需要調用服務B和C,傳統的方式我們需要在服務A中記錄服務B和C的ip及端口號。這些配置一般寫在配置文件等地方存儲。
這種做法有兩個顯而易見的缺點:1.如果將來B的ip改變了就需要修改所有調用者的ip配置。 2.難以做負載均衡
而服務發現就是用來解決這個問題的,怎麽解決呢?請看下面這張圖
這張圖中在服務消費者和服務生產者之間加了一個服務註冊中心的模塊,用上面的服務器ABC來舉例,服務B在發布的時候會在註冊中心註冊,註冊中心會記錄服務B的名字及ip地址。當服務A請求服務B的時候,只需要帶著服務B的名字來註冊中心查詢即可。集群情況下,註冊中心會有多個服務B。同時註冊中心會定期檢查每一個服務否可以正常訪問,移除不可訪問的服務。(健康檢查)
總的來說,服務發現就是通過一個標誌來獲取服務列表,並且服務列表可隨著每個服務的上線或下線動態變更
Consul術語及解釋
下面列出幾個consul中出現頻率較高的術語
- Agent,Agent是長期運行在每個consul集群成員節點上守護進程。通過命令consul agent啟動。Agent有client和server兩種模式。由於每個節點都必須運行agent,所有節點要麽是client要麽是server。所有的Agent都可以可以調用DNS或HTTP API,並負責檢查和維護服務同步。
- client 運行client模式的Agent,將所有的RPCs轉發到Server。Client是相對無狀態的。Client唯一所做的是在後臺參與LAN gossip pool。只消耗少量的資源,少量的網絡帶寬。
- Server 運行Server模式的Agent,參與Raft quorum,維護集群的狀態,響應RPC查詢,與其他數據中心交互WAN gossip,轉發查詢到Leader或遠程數據中心。
datacenter 數據中心的定義似乎是顯而易見的,有一些細節是必須考慮的。例如,在EC2,多個可用性區域是否被認為組成了單一的數據中心?我們定義數據中心是在同一個網絡環境中——私有的,低延遲,高帶寬。這不包括基於公共互聯網環境,但是對於我們而言,在同一個EC2的多個可用性區域會被認為是一個的數據中心。
- 關於client和server我搞了好久才搞明白,實際上client不存儲數據,發送到client的請求,client都會轉發給它綁定的server,也就是說client必須綁定server。server會存儲數據,如果只有一個server並在上面註冊了一個服務,這個server掛了然後你又重啟了,那麽這個服務的註冊信息仍然保存在server上。
如果你在一臺服務器上運行了一個server,它會默認有一個client綁定到server上,並且地址是127.0.0.1
consul安裝
consul下載地址:https://www.consul.io/downloads.html
我用的win10 系統,所以下載的最後一個windows64位的,下載下來有個exe文件,隨便放個到一個文件夾下就可以了。
進入cmd,轉到consul的存放目錄,打命令就可以了。
或者可以把consul的目錄路徑加入到Path環境變量中,就不用每次到目錄下打命令了
啟動consul
上面說過,consul可以以client和server的方式啟動
Server:consul agent -server -bootstrap-expect 1 -data-dir=C:\consul -node=n1 -bind=192.168.3.233 -ui-dir=C:\consul\dist -client=0.0.0.0
Client:consul agent -bootstrap-expect 1 -data-dir=C:\consul -node=n1 -bind=192.168.3.233 -ui-dir=C:\consul\dist
把-server去掉就是client模式了
- consul agent:啟動consul的命令,要麽是server要麽是client
- -bootstrap-expect:期望的server節點數目,如果集群中的server節點小於這個數據,集群則失效,並且該server也失效,一直等到集群中的數目達到相應的數量才生效,如果是1的話,代表一個server就可以了
- -data-dir:data存放的目錄,server會保存一些配置緩存等信息,存在此目錄下
- -node:該節點的名稱,急群眾名稱必須唯一
- -client:代表該server對外暴漏的client地址,0.0.0.0代表我可以通過:127.0.0.1和192.168.3.233訪問,不設置的話默認是:127.0.0.1
- -bind:這是設置集群中server之間互相通信的地址,必須可以互相訪問到
- -ui-dir:設置webui的界面,理論上通過命令可以查看到我們需要的任何信息,但是通過ui來查看更直觀
搭建集群
我開啟了兩臺虛擬機和本機一共是三臺機器,所以我搭建了三個server節點
Ser1:consul agent -server -bootstrap-expect=3 -data-dir=C:\consul -node=node1 -bind=192.168.3.233 -client=0.0.0.0
Ser2:consul agent -server -bootstrap-expect=3 -data-dir=C:\consul -node=node2 -join=192.168.3.233 -bind=192.168.3.201 -client=0.0.0.0
Ser3: consul agent -server -bootstrap-expect=3 -data-dir=C:\consul -node=node3 -join=192.168.3.233 -bind=192.168.3.243 -client=0.0.0.0
-join:表示加入到哪個集群內,ser2中我們指定加入到了ser1中,這時候ser1和ser2組成了集群,ser3我們可以指定加入到ser1和ser2,不管加入哪個最終這三個server都組成了一個集群,最終三個server商量了一下選出了一個leader
服務註冊
可以通過命令來註冊服務,因為最終是要在.net core上使用,所以我就直接貼上.net core中的相關代碼
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLifeTime)
{
string ip = Configuration["ip"];
string port = Configuration["port"];
string serviceName = "MsgService";
string serviceId = serviceName + Guid.NewGuid();
Action<ConsulClientConfiguration> ConsulConfig = (config) =>
{
config.Address = new Uri("http://192.168.3.201:8500"); //服務註冊的地址,集群中任意一個地址
config.Datacenter = "dc1";
};
using (var consulClient = new ConsulClient(ConsulConfig))
{
AgentServiceRegistration asr = new AgentServiceRegistration
{
Address = ip,
Port = Convert.ToInt32(port),
ID = serviceId,
Name = serviceName,
Check = new AgentServiceCheck
{
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),
HTTP = $"http://{ip}:{port}/api/Health",//健康檢查訪問的地址
Interval = TimeSpan.FromSeconds(10), //健康檢查的間隔時間
Timeout = TimeSpan.FromSeconds(5), //多久代表超時
},
};
consulClient.Agent.ServiceRegister(asr).Wait();
}
//註銷Consul
appLifeTime.ApplicationStopped.Register(() =>
{
using (var consulClient = new ConsulClient(ConsulConfig))
{
consulClient.Agent.ServiceDeregister(serviceId).Wait(); //從consul集群中移除服務
}
});
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseMvc();
}
運行程序後向consul集群註冊了一個服務,訪問集群的任何一個ip都可取到該服務的ip。客戶端查詢服務的代碼如下:
static void Main(string[] args)
{
using (var consul = new Consul.ConsulClient(c =>
{
c.Address = new Uri("http://192.168.3.233:8500"); //Consul地址
}))
{
var services = consul.Catalog.Service("MsgService").Result.Response;
foreach (var s1 in services)
{
Console.WriteLine($"ID={s1.ServiceID},Service={s1.ServiceName},Addr={s1.Address},Port={s1.ServicePort}");
}
}
}
這樣我們一個基本的consul集群就可以正常使用了
對於consul和服務發現目前還只是剛剛開始接觸。還是有很多問題暫時沒有搞明白。
比如客戶端連接的server突然掛了怎麽辦如何切換到另一個server?以及一個服務下線了如何通知客戶端刪除緩存等等。還請大家不吝賜教
Consul在.Net Core中初體驗