前言
在云計(jì)算和容器化技術(shù)發(fā)展火熱的當(dāng)下,對于微服務(wù)架構(gòu),服務(wù)注冊與發(fā)現(xiàn)組件是必不可少的。在傳統(tǒng)的服務(wù)架構(gòu)中,服務(wù)的規(guī)模處于運(yùn)維人員的可控范圍內(nèi)。當(dāng)部署服務(wù)的多個節(jié)點(diǎn)時,一般使用靜態(tài)配置的方式實(shí)現(xiàn)服務(wù)信息的設(shè)定。在微服務(wù)應(yīng)用中,服務(wù)實(shí)例的數(shù)量和網(wǎng)絡(luò)地址都是動態(tài)變化的,這對系統(tǒng)運(yùn)維提出了巨大的挑戰(zhàn)。因此,動態(tài)的服務(wù)注冊與發(fā)現(xiàn)就顯得尤為重要。
在一個分布式系統(tǒng)中,服務(wù)注冊與發(fā)現(xiàn)組件主要解決兩個問題:服務(wù)注冊和服務(wù)發(fā)現(xiàn)。
服務(wù)注冊:服務(wù)實(shí)例將自身服務(wù)信息注冊到注冊中心。這部分服務(wù)信息包括服務(wù)所在主機(jī)IP和提供服務(wù)的Port,以及暴露服務(wù)自身狀態(tài)以及訪問協(xié)議等信息。
服務(wù)發(fā)現(xiàn):服務(wù)實(shí)例請求注冊中心獲取所依賴服務(wù)信息。服務(wù)實(shí)例通過注冊中心,獲取到注冊到其中的服務(wù)實(shí)例的信息,通過這些信息去請求它們提供的服務(wù)。
除此之外,服務(wù)注冊與發(fā)現(xiàn)需要關(guān)注監(jiān)控服務(wù)實(shí)例運(yùn)行狀態(tài)、負(fù)載均衡等問題。
監(jiān)控:微服務(wù)應(yīng)用中,服務(wù)處于動態(tài)變化的情況,需要一定機(jī)制處理無效的服務(wù)實(shí)例。一般來講,服務(wù)實(shí)例與注冊中心在注冊后通過心跳的方式維系聯(lián)系,一旦心跳缺少,對應(yīng)的服務(wù)實(shí)例會被注冊中心剔除。
負(fù)載均衡:同一服務(wù)可能同時存在多個實(shí)例,需要正確處理對該服務(wù)的負(fù)載均衡。
CAP原則,指的是在一個分布式系統(tǒng)中,Consistency(一致性)、Availability(可用性)、Partition Tolerance(分區(qū)容錯性),不能同時成立。
一致性:它要求在同一時刻點(diǎn),分布式系統(tǒng)中的所有數(shù)據(jù)備份都處于同一狀態(tài)。
可用性:在系統(tǒng)集群的一部分節(jié)點(diǎn)宕機(jī)后,系統(tǒng)依然能夠響應(yīng)用戶的請求。
分區(qū)容錯性:在網(wǎng)絡(luò)區(qū)間通信出現(xiàn)失敗,系統(tǒng)能夠容忍。
一般來講,基于網(wǎng)絡(luò)的不穩(wěn)定性,分布容錯是不可避免的,所以我們默認(rèn)CAP中的P總是成立的。
一致性的強(qiáng)制數(shù)據(jù)統(tǒng)一要求,必然會導(dǎo)致在更新數(shù)據(jù)時部分節(jié)點(diǎn)處于被鎖定狀態(tài),此時不可對外提供服務(wù),影響了服務(wù)的可用性,反之亦然。因此一致性和可用性不能同時滿足。
我們接下來介紹的服務(wù)注冊和發(fā)現(xiàn)組件中,Eureka滿足了其中的AP,Consul和Zookeeper滿足了其中的CP。
Eureka是在Java語言上,基于Restful Api開發(fā)的服務(wù)注冊與發(fā)現(xiàn)組件,由Netflix開源。遺憾的是,目前Eureka僅開源到1.X版本,2.X版本已經(jīng)宣布閉源。
Eureka采用的是Server/Client的模式進(jìn)行設(shè)計(jì)。Server扮演了服務(wù)注冊中心的角色,為Client提供服務(wù)注冊和發(fā)現(xiàn)的功能,維護(hù)著注冊到自身的Client的相關(guān)信息,同時提供接口給Client獲取到注冊表中其他服務(wù)的信息。Client將有關(guān)自己的服務(wù)的信息通過一定的方式登記到Server上,并在正常范圍內(nèi)維護(hù)自己信息的一致性,方便其他服務(wù)發(fā)現(xiàn)自己,同時可以通過Server獲取到自己的依賴的其他服務(wù)信息,從而完成服務(wù)調(diào)用。
它的架構(gòu)圖如下所示:

Application Service: 作為Eureka Client,扮演了服務(wù)的提供者,提供業(yè)務(wù)服務(wù),向Eureka Server注冊和更新自己的信息,同時能從Eureka Server的注冊表中獲取到其他服務(wù)的信息。
Eureka Server:扮演服務(wù)注冊中心的角色,提供服務(wù)注冊和發(fā)現(xiàn)的功能,每個Eureka Cient向Eureka Server注冊自己的信息,也可以通過Eureka Server獲取到其他服務(wù)的信息達(dá)到發(fā)現(xiàn)和調(diào)用其他服務(wù)的目的。
Application Client:作為Eureka Client,扮演了服務(wù)消費(fèi)者,通過Eureka Server獲取到注冊到上面的其他服務(wù)的信息,從而根據(jù)信息找到所需的服務(wù)發(fā)起遠(yuǎn)程調(diào)用。
Replicate: Eureka Server中的注冊表信息的同步拷貝,保持不同的Eureka Server集群中的注冊表中的服務(wù)實(shí)例信息的一致性。提供了數(shù)據(jù)的最終一致性。
Make Remote Call: 服務(wù)之間的遠(yuǎn)程調(diào)用。
Register: 注冊服務(wù)實(shí)例,Client端向Server端注冊自身的元數(shù)據(jù)以進(jìn)行服務(wù)發(fā)現(xiàn)。
Renew:續(xù)約,通過發(fā)送心跳到Server維持和更新注冊表中的服務(wù)實(shí)例元數(shù)據(jù)的有效性。當(dāng)在一定時長內(nèi)Server沒有收到Client的心跳信息,將默認(rèn)服務(wù)下線,將服務(wù)實(shí)例的信息從注冊表中刪除。
Cancel:服務(wù)下線,Client在關(guān)閉時主動向Server注銷服務(wù)實(shí)例元數(shù)據(jù),這時Client的的服務(wù)實(shí)例數(shù)據(jù)將從Server的注冊表中刪除。
Eureka中沒有使用任何的數(shù)據(jù)強(qiáng)一致性算法保證不同集群間的Server的數(shù)據(jù)一致,僅通過數(shù)據(jù)拷貝的方式爭取注冊中心數(shù)據(jù)的最終一致性,雖然放棄數(shù)據(jù)強(qiáng)一致性但是換來了Server的可用性,降低了注冊的代價,提高了集群運(yùn)行的健壯性。
Consul是由HashiCorp基于Go語言開發(fā)的支持多數(shù)據(jù)中心分布式高可用的服務(wù)發(fā)布和注冊服務(wù)軟件,采用Raft算法保證服務(wù)的一致性,且支持健康檢查。
Consul采用主從模式的設(shè)計(jì),使得集群的數(shù)量可以大規(guī)模擴(kuò)展,集群間通過RPC的方式調(diào)用(HTTP和DNS)。它的結(jié)構(gòu)圖如下所示:

Client:作為一個代理(非微服務(wù)實(shí)例),它將轉(zhuǎn)發(fā)所有的RPC請求到Server中。作為相對無狀態(tài)的服務(wù),它不持有任何注冊信息。
Server:作為一個具備擴(kuò)展功能的代理,它將響應(yīng)RPC查詢、參與Raft選舉、維護(hù)集群狀態(tài)和轉(zhuǎn)發(fā)查詢給Leader等。
Leader-Server:一個數(shù)據(jù)中心的所有Server都作為Raft節(jié)點(diǎn)集合的一部分。其中Leader將負(fù)責(zé)所有的查詢和事務(wù)(如服務(wù)注冊),同時這些事務(wù)也會被復(fù)制到所有其他的節(jié)點(diǎn)。
Data Center:數(shù)據(jù)中心作為一個私有的,低延遲和高帶寬的一個網(wǎng)絡(luò)環(huán)境。每個數(shù)據(jù)中心會存在Consul集群,一般建議Server是3-5臺(考慮到Raft算法在可用性和性能上取舍),而Leader只能唯一,Client的數(shù)量沒有限制,可以輕松擴(kuò)展。
Raft算法將Server分為三種類型:Leader、Follower和Candidate。Leader處理所有的查詢和事務(wù),并向Follower同步事務(wù)。Follower會將所有的RPC查詢和事務(wù)轉(zhuǎn)發(fā)給Leader處理,它僅從Leader接受事務(wù)的同步。數(shù)據(jù)的一致性以Leader中的數(shù)據(jù)為準(zhǔn)實(shí)現(xiàn)。
在節(jié)點(diǎn)初始啟動時,節(jié)點(diǎn)的Raft狀態(tài)機(jī)將處于Follower狀態(tài)等待來來自Leader節(jié)點(diǎn)的心跳。如果在一定時間周期內(nèi)沒有收到Leader節(jié)點(diǎn)的心跳,節(jié)點(diǎn)將發(fā)起選舉。
Follower節(jié)點(diǎn)選舉時會將自己的狀態(tài)切換為Candidate,然后向集群中其它Follower節(jié)點(diǎn)發(fā)送請求,詢問其是否選舉自己成為Leader。當(dāng)收到來自集群中過半數(shù)節(jié)點(diǎn)的接受投票后,節(jié)點(diǎn)即成為Leader,開始接收Client的事務(wù)處理和查詢并向其它的Follower節(jié)點(diǎn)同步事務(wù)。Leader節(jié)點(diǎn)會定時向Follower發(fā)送心跳來保持其地位。
Gossip協(xié)議是為了解決分布式環(huán)境下監(jiān)控和事件通知的瓶頸。Gossip協(xié)議中的每個Agent會利用Gossip協(xié)議互相檢查在線狀態(tài),分擔(dān)了服務(wù)器節(jié)點(diǎn)的心跳壓力,通過Gossip廣播的方式發(fā)送消息。
所有的Agent都運(yùn)行著Gossip協(xié)議。服務(wù)器節(jié)點(diǎn)和普通Agent都會加入這個Gossip集群,收發(fā)Gossip消息。每隔一段時間,每個節(jié)點(diǎn)都會隨機(jī)選擇幾個節(jié)點(diǎn)發(fā)送Gossip消息,其他節(jié)點(diǎn)會再次隨機(jī)選擇其他幾個節(jié)點(diǎn)接力發(fā)送消息。這樣一段時間過后,整個集群都能收到這條消息。
基于Raft算法,Consul提供強(qiáng)一致性的注冊中心服務(wù),但是由于Leader節(jié)點(diǎn)承擔(dān)了所有的處理工作,勢必加大了注冊和發(fā)現(xiàn)的代價,降低了服務(wù)的可用性。通過Gossip協(xié)議,Consul可以很好地監(jiān)控Consul集群的運(yùn)行,同時可以方便通知各類事件,如Leader選擇發(fā)生、Server地址變更等。
Zookeeper是由Google開源的在Java語言上實(shí)現(xiàn)的分布式協(xié)調(diào)服務(wù),是Hadoop和Hbase的重要組件,提供了數(shù)據(jù)/發(fā)布訂閱、負(fù)載均衡、分布式同步等功能。
Zookeeper也是基于主從架構(gòu),搭建了一個可高擴(kuò)展的服務(wù)集群,其服務(wù)架構(gòu)如下:

Leader-Server:Leader負(fù)責(zé)進(jìn)行投票的發(fā)起和決議,更新系統(tǒng)中的數(shù)據(jù)狀態(tài)
Server:Server中存在兩種類型:Follower和Observer。其中Follower接受客戶端的請求并返回結(jié)果(事務(wù)請求將轉(zhuǎn)發(fā)給Leader處理),并在選舉過程中參與投票;Observer與Follower功能一致,但是不參與投票過程,它的存在是為了提高系統(tǒng)的讀取速度
Client:請求發(fā)起方,Server和Client之間可以通過長連接的方式進(jìn)行交互。如發(fā)起注冊或者請求集群信息等。
ZooKeeper Atomic Broadcast protocol是專門設(shè)計(jì)給Zookeeper用于實(shí)現(xiàn)分布式系統(tǒng)數(shù)據(jù)的一致性,是在Paxos算法基礎(chǔ)上發(fā)展而來。它使用了單一的Leader來接受和處理客戶端的所有事務(wù)請求,并將服務(wù)器數(shù)據(jù)的狀態(tài)變更以事務(wù)Proposal的形式廣播到所有的Server中。同時它保證Leader出現(xiàn)異常時,集群依舊能夠正常工作。Zab包含兩種基本模式:崩潰恢復(fù)和消息廣播。
崩潰恢復(fù):Leader服務(wù)器出現(xiàn)宕機(jī),或者因?yàn)榫W(wǎng)絡(luò)原因?qū)е翷eader服務(wù)器失去了與過半 Follower的聯(lián)系,那么就會進(jìn)入崩潰恢復(fù)模式從而選舉新的Leader。Leader選舉算法不僅僅需要讓Leader自己知道其自身已經(jīng)被選舉為Leader,同時還需要讓集群中的所有其他服務(wù)器也能夠快速地感知到選舉產(chǎn)生的新的Leader。當(dāng)選舉產(chǎn)生了新的Leader,同時集群中有過半的服務(wù)器與該Leader完成了狀態(tài)同步之后,Zab協(xié)議就會退出崩潰恢復(fù)模式,進(jìn)入消息廣播模式。
消息廣播:Zab協(xié)議的消息廣播過程類似二階段提供過程,是一種原子廣播的協(xié)議。當(dāng)接受到來自Client的事務(wù)請求(如服務(wù)注冊)(所有的事務(wù)請求都會轉(zhuǎn)發(fā)給Leader),Leader會為事務(wù)生成對應(yīng)的Proposal,并為其分配一個全局唯一的ZXID。Leader服務(wù)器與每個Follower之間都有一個單獨(dú)的隊(duì)列進(jìn)行收發(fā)消息,Leader將生成的Proposal發(fā)送到隊(duì)列中。Follower從隊(duì)列中取出Proposal進(jìn)行事務(wù)消費(fèi),消費(fèi)完畢后發(fā)送一個ACK給Leader。當(dāng)Leader接受到半數(shù)以上的Follower發(fā)送的ACK投票,它將發(fā)送Commit給所有Follower通知其對事務(wù)進(jìn)行提交,Leader本身也會提交事務(wù),并返回給處理成功給對應(yīng)的客戶端。Follower只有將隊(duì)列中Proposal都同步消費(fèi)后才可用。
基于Zab協(xié)議,Zookeeper可以用于構(gòu)建具備數(shù)據(jù)強(qiáng)一致性的服務(wù)注冊與發(fā)現(xiàn)中心,而與此相對地犧牲了服務(wù)的可用性和提高了注冊需要的時間。
想了解更多的可以加扣 群 854 393 687
最后我們通過一張表格大致了解Eureka、Consul、Zookeeper的異同點(diǎn)。選擇什么類型的服務(wù)注冊與發(fā)現(xiàn)組件可以根據(jù)自身項(xiàng)目要求決定。
組件名語言CAP一致性算法服務(wù)健康檢查對外暴露接口Spring Cloud集成
EurekaJavaAP無可配支持HTTP已集成
ConsulGoCPRaft支持HTTP/DNS已集成
ZookeeperJavaCPPaxos支持客戶端已集成
如有錯誤,請指出,謝謝??!