一、基本功能
對於微服務架構,服務注冊與發現組件是必不可少的。在傳統的服務架構中,服務的規模處於運維人員的可控范圍內。當部署服務的多個節點時,一般使用靜態配置的方式實現服務信息的設定。在微服務應用中,服務實例的數量和網絡地址都是動態變化的。
服務注冊和服務發現
在一個分布式系統中,服務注冊與發現組件主要解決兩個問題:服務注冊和服務發現。
服務注冊:服務實例將自身服務信息注冊到注冊中心。這部分服務信息包括服務所在主機IP和提供服務的Port,以及暴露服務自身狀態以及訪問協議等信息。
服務發現:服務實例請求注冊中心獲取所依賴服務信息。服務實例通過注冊中心,獲取到注冊到其中的服務實例的信息,通過這些信息去請求它們提供的服務。
除此之外,服務注冊與發現需要關注監控服務實例運行狀態、負載均衡等問題。
監控:微服務應用中,服務處於動態變化的情況,需要一定機制處理無效的服務實例。一般來講,服務實例與注冊中心在注冊后通過心跳的方式維系聯系,一旦心跳缺少,對應的服務實例會被注冊中心剔除。
負載均衡:同一服務可能同時存在多個實例,需要正確處理對該服務的負載均衡。
CAP原則
CAP原則,指的是在一個分布式系統中,Consistency(一致性)、Availability(可用性)、Partition Tolerance(分區容錯性),不能同時成立。
一致性:它要求在同一時刻點,分布式系統中的所有數據備份都處於同一狀態。
可用性:在系統集群的一部分節點宕機后,系統依然能夠響應用戶的請求。
分區容錯性:在網絡區間通信出現失敗,系統能夠容忍。
一般來講,基於網絡的不穩定性,分布容錯是不可避免的,所以我們默認CAP中的P總是成立的。
一致性的強制數據統一要求,必然會導致在更新數據時部分節點處於被鎖定狀態,此時不可對外提供服務,影響了服務的可用性,反之亦然。因此一致性和可用性不能同時滿足(即只存在AP或CP)。
接下來介紹的服務注冊和發現組件中,Eureka滿足了其中的AP,Consul和Zookeeper滿足了其中的CP。
二、Eureka
Eureka是在Java語言上,基於Restful Api開發的服務注冊與發現組件,由Netflix開源。
eureka架構圖

Replicate: Eureka Server中的注冊表信息的同步拷貝,保持不同的Eureka Server集群中的注冊表中的服務實例信息的一致性。提供了數據的最終一致性。
Make Remote Call: 服務之間的遠程調用。
Register: 注冊服務實例,Client端向Server端注冊自身的元數據以進行服務發現。
Renew:續約,通過發送心跳到Server維持和更新注冊表中的服務實例元數據的有效性。當在一定時長內Server沒有收到Client的心跳信息,將默認服務下線,將服務實例的信息從注冊表中刪除。
Cancel:服務下線,Client在關閉時主動向Server注銷服務實例元數據,這時Client的的服務實例數據將從Server的注冊表中刪除。
三、Consul
Consul是由HashiCorp基於Go語言開發的支持多數據中心分布式高可用的服務發布和注冊服務軟件,采用Raft算法保證服務的一致性,且支持健康檢查。
Consul采用主從模式的設計,使得集群的數量可以大規模擴展,集群間通過RPC的方式調用(HTTP和DNS)。它的結構圖如下所示:
Client:作為一個代理(非微服務實例),它將轉發所有的RPC請求到Server中。作為相對無狀態的服務,它不持有任何注冊信息。
Server:作為一個具備擴展功能的代理,它將響應RPC查詢、參與Raft選舉、維護集群狀態和轉發查詢給Leader等。
Leader-Server:一個數據中心的所有Server都作為Raft節點集合的一部分。其中Leader將負責所有的查詢和事務(如服務注冊),同時這些事務也會被復制到所有其他的節點。
Data Center:數據中心作為一個私有的,低延遲和高帶寬的一個網絡環境。每個數據中心會存在Consul集群,一般建議Server是3-5台(考慮到Raft算法在可用性和性能上取舍),而Leader只能唯一,Client的數量沒有限制,可以輕松擴展。
Raft算法
Gossip協議
Gossip協議是為了解決分布式環境下監控和事件通知的瓶頸。Gossip協議中的每個Agent會利用Gossip協議互相檢查在線狀態,分擔了服務器節點的心跳壓力,通過Gossip廣播的方式發送消息。
所有的Agent都運行着Gossip協議。服務器節點和普通Agent都會加入這個Gossip集群,收發Gossip消息。每隔一段時間,每個節點都會隨機選擇幾個節點發送Gossip消息,其他節點會再次隨機選擇其他幾個節點接力發送消息。這樣一段時間過后,整個集群都能收到這條消息。
基於Raft算法,Consul提供強一致性的注冊中心服務,但是由於Leader節點承擔了所有的處理工作,勢必加大了注冊和發現的代價,降低了服務的可用性。通過Gossip協議,Consul可以很好地監控Consul集群的運行,同時可以方便通知各類事件,如Leader選擇發生、Server地址變更等。
四、Zookeeper
Zookeeper是由Google開源的在Java語言上實現的分布式協調服務,是Hadoop和Hbase的重要組件,提供了數據/發布訂閱、負載均衡、分布式同步等功能。
Zookeeper也是基於主從架構,搭建了一個可高擴展的服務集群,其服務架構如下:

Leader-Server:Leader負責進行投票的發起和決議,更新系統中的數據狀態
Server:Server中存在兩種類型:Follower和Observer。其中Follower接受客戶端的請求並返回結果(事務請求將轉發給Leader處理),並在選舉過程中參與投票;Observer與Follower功能一致,但是不參與投票過程,它的存在是為了提高系統的讀取速度
Client:請求發起方,Server和Client之間可以通過長連接的方式進行交互。如發起注冊或者請求集群信息等。
Zab協議
ZooKeeper Atomic Broadcast protocol是專門設計給Zookeeper用於實現分布式系統數據的一致性,是在Paxos算法基礎上發展而來。它使用了單一的Leader來接受和處理客戶端的所有事務請求,並將服務器數據的狀態變更以事務Proposal的形式廣播到所有的Server中。同時它保證Leader出現異常時,集群依舊能夠正常工作。Zab包含兩種基本模式:崩潰恢復和消息廣播。
崩潰恢復:Leader服務器出現宕機,或者因為網絡原因導致Leader服務器失去了與過半 Follower的聯系,那么就會進入崩潰恢復模式從而選舉新的Leader。Leader選舉算法不僅僅需要讓Leader自己知道其自身已經被選舉為Leader,同時還需要讓集群中的所有其他服務器也能夠快速地感知到選舉產生的新的Leader。當選舉產生了新的Leader,同時集群中有過半的服務器與該Leader完成了狀態同步之后,Zab協議就會退出崩潰恢復模式,進入消息廣播模式。
消息廣播:Zab協議的消息廣播過程類似二階段提供過程,是一種原子廣播的協議。當接受到來自Client的事務請求(如服務注冊)(所有的事務請求都會轉發給Leader),Leader會為事務生成對應的Proposal,並為其分配一個全局唯一的ZXID。Leader服務器與每個Follower之間都有一個單獨的隊列進行收發消息,Leader將生成的Proposal發送到隊列中。Follower從隊列中取出Proposal進行事務消費,消費完畢后發送一個ACK給Leader。當Leader接受到半數以上的Follower發送的ACK投票,它將發送Commit給所有Follower通知其對事務進行提交,Leader本身也會提交事務,並返回給處理成功給對應的客戶端。Follower只有將隊列中Proposal都同步消費后才可用。
基於Zab協議,Zookeeper可以用於構建具備數據強一致性的服務注冊與發現中心,而與此相對地犧牲了服務的可用性和提高了注冊需要的時間。
參考:
https://www.jianshu.com/p/a882e7a2d79f