SpringCloud微服務註冊中心Consul

前言

SpringCoud核心組件中一文,首先提到了SringCoud註冊中心Eureka,後臺Eureka官方已不再維護,於是有了Eureka的替代方案Consul,下面具體說一下Consul註冊中心。

一、Consul服務註冊中心的整體架構

1、consul內部原理

在這裏插入圖片描述
首先Consul支持多數據中心,在上圖中有兩個DataCenter,他們通過Internet互聯,同時請注意爲了提高通信效率,只有Server節點才加入跨數據中心的通信。

在單個數據中心中,Consul分爲Client和Server兩種節點(所有的節點都具備Agent的功能)。

  1. Consule Server節點:保存整個集羣的數據,
  2. Consule Client負責健康檢查及轉發數據請求到Server(Client節點當然也保存註冊到本節點的服務數據);
  3. Server節點有一個Leader和多個Follower,Leader節點會將數據同步到Follower,Server的數量推薦是3個或者5個,在Leader掛掉的時候會啓動選舉機制產生一個新的Leader。

集羣內的Consul節點通過gossip協議(流言協議)維護成員關係,也就是說某個節點了解集羣內現在還有哪些節點,這些節點是Client還是Server。單個數據中心的流言協議同時使用TCP和UDP通信,並且都使用8301端口。跨數據中心的流言協議也同時使用TCP和UDP通信,端口使用8302。

集羣內數據的讀寫請求既可以直接發到Server,也可以通過Client使用RPC轉發到Server,請求最終會到達Leader節點,在允許數據輕微陳舊的情況下,讀請求也可以在普通的Server節點完成,集羣內數據的讀寫和複製都是通過TCP的8300端口完成。

2、consul服務發現原理

服務發現的完整流程:
在這裏插入圖片描述
上面是一個consul集羣。
(1)、服務器Server1、Server2、Server3上分別部署了Consul Server,假設通過選舉,得到Server2上的Consul Server節點爲Leader,其它爲Follower。

(2)、服務器Server4和Server5上,通過Consul Client分別註冊微服務A、B、C,這裏每個微服務分別部署在了兩個服務器上

微服務註冊到Consul方式:

  • 可以通過HTTP API(8500端口)的方式,
  • 也可以通過Consul配置文件的方式。

Consul Client會將註冊信息通過RPC轉發到Consul Server,服務信息保存在Server的各個節點中,並且通過Raft實現了強一致性;
Consul Client還會對註冊到當前節點的服務進行健康檢查,並將服務狀態同步到Server,當然也是強一致性的。

(3)、服務器Server6中微服務 D需要訪問微服務B,這時候微服務D首先訪問本機Consul Client提供的HTTP API,本機Client會將請求轉發到Consul Server,Consul Server查詢到微服務 B當前的信息返回,最終微服務D拿到了微服務B的所有部署的IP和端口,然後就可以選擇微服務B的其中一個部署並向其發起請求了。

3、docer安裝consul

安裝Docker

通過這個地址下載安裝:
https://store.docker.com/editions/community/docker-ce-desktop-windows
安裝完成後打開 Windows PowerShell,輸入docker –version,如果正常輸出docker版本就可以了。

啓動Consul集羣

在 Windows PowerShell中執行命令拉取最新版本的Consul鏡像:

docker pull consul

然後就可以啓動集羣了,這裏啓動4個Consul Agent(3個Server,1個Client)。3個Server中會選舉出一個leader。

#啓動第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

第1個啓動容器的IP一般是172.17.0.2,後邊啓動的幾個容器IP會排着來:172.17.0.3、172.17.0.4、172.17.0.5。

進入容器consul1:

docker exec -it consul1 /bin/sh

#執行ls後可以看到consul就在根目錄
ls

輸入exit可以跳出容器。

4、Consul的健康檢查

Consul做服務發現是專業的,健康檢查是其中一項必不可少的功能,其提供Script/TCP/HTTP+Interval,以及TTL等多種方式。服務的健康檢查由服務註冊到的Agent來處理,這個Agent既可以是Client也可以是Server。

集中式的心跳機制,比如傳統的Eureka,是讓各個服務都必須每隔一定時間發送心跳到Eureka Server。
如果一段時間沒收到心跳,那麼就認爲這個服務宕機了。

但是這種集中式的心跳機制會對Eureka Server造成較大的心跳請求壓力,實際上平時Eureka Server接收最多的請求之一就是成千上萬服務發送過來的心跳請求。

所以Consul在這塊進行了架構優化,引入了Agent概念
每個機器上的Consul Agent會不斷的發送請求檢查服務是否健康,是否宕機。如果服務宕機了,那麼就會通知Consul Server。

Consul與ZooKeeper、etcd的區別

後邊這兩個工具是通過鍵值存儲來實現服務的註冊與發現。

  • ZooKeeper利用臨時節點的機制,業務服務啓動時創建臨時節點,節點在服務就在,節點不存在服務就不存在。
  • etcd利用TTL機制,業務服務啓動時創建鍵值對,定時更新ttl,ttl過期則服務不可用。

健康檢查能不能支持故障轉移?

上邊提到健康檢查是由服務註冊到的Agent來處理的,那麼如果這個Agent掛掉了,會不會有別的Agent來接管健康檢查呢?答案是否定的

5、Consul的其它部署架構

如果你實在不想在每個主機部署Consul Client,還有一個多路註冊的方案可供選擇,這是交流羣中獲得的思路

在這裏插入圖片描述
如圖所示,在專門的服務器上部署Consul Client,然後每個服務都註冊到多個Client,這裏爲了避免服務單點問題還是每個服務部署多份,需要服務發現時,程序向一個提供負載均衡的程序發起請求,該程序將請求轉發到某個Consul Client。這種方案需要注意將Consul的8500端口綁定到私網IP上,默認只有127.0.0.1。

這個架構的優勢:

  • Consul節點服務器與應用服務器隔離,互相干擾少;
  • 不用每臺主機都部署Consul,方便Consul的集中管理;
  • 某個Consul Client掛掉的情況下,註冊到其上的服務仍有機會被訪問到;

但也需要注意其缺點:

  • 引入更多技術棧:負載均衡的實現,不僅要考慮Consul Client的負載均衡,還要考慮負載均衡本身的單點問題。
  • Client的節點數量:單個Client如果註冊的服務太多,負載較重,需要有個算法(比如hash一致)合理分配每個Client上的服務數量,以及確定Client的總體數量。
  • 服務發現要過濾掉重複的註冊,因爲註冊到了多個節點會認爲是多個部署(DNS接口不會有這個問題)。

這個方案其實還可以優化,服務發現使用的負載均衡可以直接代理Server節點,因爲相關請求還是會轉發到Server節點,不如直接就發到Server。

是否可以只有Server?

這個問題的答案還是有關服務數量的問題,首先Server的節點數量不是越多越好,3個或者5個是推薦的數量,數量越多數據同步的處理越慢(強一致性);然後每個節點可以註冊的服務數量是有上限的,這個受限於軟硬件的處理能力。所以如果你的服務只有10個左右,只有Server問題是不大的,但是這時候有沒有必要使用Consul呢?因此正常使用Consul的時候還是要有Client纔好,這也符合Consul的反熵設計。

大家可以將這個部署架構與前文提到的普適架構對比下,看看哪個更適合自己,或者你有更好的方案歡迎分享出來。

6、Consul如何通過Raft協議實現強一致性?

首先,Consul Server是部署集羣的,而且他會選舉出來一臺Server作爲Leader。

接下來各個服務發送的註冊請求都會落地給Leader,由Leader同步給其他Follower。

所以首先第一點,Leader Server是絕對有最新的服務註冊信息的。

比如庫存服務發起註冊了,那麼Leader Server上一定有庫存服務的註冊信息。

接着如果比如訂單服務要發現庫存服務的話,這個查詢請求會發送給Leader Server。

這樣服務註冊和發現,都是通過一臺Leader Server來進行的,就可以保證服務註冊數據的強一致性了,大家看下圖。

假如庫存服務在註冊的時候數據剛寫到Leader Server,結果Leader Server就宕機了?

那麼此時這條註冊數據就丟失了,訂單服務就沒法發現那個庫存服務了。沒關係,這裏Consul會基於Raft協議來解決這個問題。

首先,庫存服務註冊到Leader Server的時候,會採取Raft協議,要求必須讓Leader Server把這條註冊數據複製給大部分的Follower Server纔算成功。

這就保證了,如果你認爲自己註冊成功了,那麼必然是多臺Consul Server都有這條註冊數據了。

如果你剛發送給Leader Server他自己就宕機了,那麼這次註冊會認爲失敗。

此時,Consul Server集羣會重新選舉一個Leader Server出來,你需要再次重新註冊。

這樣就可以保證你註冊成功的數據絕對不會丟,然後別人發現服務的時候一定可以從Leader Server上獲取到最新的強一致的註冊數據。
原文:

http://blog.bossma.cn/consul/consul-service-register-and-discovery-style/

https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484680&idx=1&sn=d25e1f81ad75f68dd88755173843efad&chksm=fba6ed0bccd1641d7edfd05431904b96f2e3da7c04b3a75c2a350e374733f59971c01ddd9ae6&scene=21#wechat_redirect

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章