這篇文章,主要講述 Zookeeper、Eureka、Nacos、Consul 和 Etcd 這 5 種註冊中心, 無論是面試,還是用於技術選型,都有非常強的參考價值。
全文接近 8千字 ,有點長, 建議先收藏,再慢慢看 ,下面是文章目錄:
01 註冊中心基本概念
1.1 什麽是註冊中心?
註冊中心主要有三種角色:
服務提供者(RPC Server) :在啟動時,向 Registry 註冊自身服務,並向 Registry 定期發送心跳匯報存活狀態。
服務消費者(RPC Client) :在啟動時,向 Registry 訂閱服務,把 Registry 返回的服務節點列表緩存在本地記憶體中,並與 RPC Sever 建立連線。
服務註冊中心(Registry) :用於保存 RPC Server 的註冊資訊,當 RPC Server 節點發生變更時,Registry 會同步變更,RPC Client 感知後會重新整理本地 記憶體中緩存的服務節點列表。
最後,RPC Client 從本地緩存的服務節點列表中,基於負載均衡演算法選擇一台 RPC Sever 發起呼叫。
1.2 註冊中心需要實作功能
根據註冊中心原理的描述,註冊中心必須實作以下功能,偷個懶,直接貼幅圖:
02 註冊中心基礎掃盲
2.1 CAP理論
CAP理論是分布式架構中重要理論:
一致性(Consistency):所有節點在同一時間具有相同的數據;
可用性(Availability) :保證每個請求不管成功或者失敗都有響應;
分隔容忍(Partition tolerance) :系統中任意資訊的遺失或失敗不會影響系統的繼續運作。
關於 P 的理解,我覺得是在整個系統中某個部份,掛掉了,或者宕機了,並不影響整個系統的運作或者說使用,而可用性是,某個系統的某個節點掛了,但是並不影響系統的接受或者發出請求。
CAP 不可能都取,只能取其中2個的原因如下:
如果C是第一需求的話,那麽會影響A的效能,因為要數據同步,不然請求結果會有差異,但是數據同步會消耗時間,期間可用性就會降低。
如果A是第一需求,那麽只要有一個服務在,就能正常接受請求,但是對於返回結果變不能保證,原因是,在分布式部署的時候,數據一致的過程不可能想切路線那麽快。
再如果,同時滿足一致性和可用性,那麽分區容錯就很難保證了,也就是單點,也是分布式的基本核心。
2.2 分布式系統協定
一致性協定演算法主要有Paxos、Raft、ZAB。
Paxos演算法是Leslie Lamport在1990年提出的一種基於訊息傳遞的一致性演算法,非常難以理解,基於Paxos協定的數據同步與傳統主備方式最大的區別在於:Paxos只需超過半數的副本線上且相互通訊正常,就可以保證服務的持續可用,且數據不遺失。
Raft是史丹佛大學的Diego Ongaro、John Ousterhout兩個人以易理解為目標設計的一致性演算法,已經有了十幾種語言的Raft演算法實作框架,較為出名的有etcd,Google的Kubernetes也是用了etcd作為他的服務發現框架。
Raft是Paxos的簡化版,與Paxos相比,Raft強調的是易理解、易實作,Raft和Paxos一樣只要保證超過半數的節點正常就能夠提供服務。
ZooKeeper Atomic Broadcast (ZAB, ZooKeeper原子訊息廣播協定)是ZooKeeper實作分布式數據一致性的核心演算法,ZAB借鑒Paxos演算法,但又不像Paxos演算法那樣,是一種通用的分布式一致性演算法,它是一種特別為ZooKeeper專門設計的支持崩潰恢復的原子廣播協定。
03 常用註冊中心
這裏主要介紹5種常用的註冊中心,分別為 Zookeeper、Eureka、Nacos、Consul和ETCD 。
3.1 Zookeeper
這個說起來有點意思的是官方並沒有說他是一個註冊中心,但是國內Dubbo場景下很多都是使用Zookeeper來完成了註冊中心的功能。
當然這有很多歷史原因,這裏我們就不追溯了。ZooKeeper是非常經典的服務註冊中心中介軟體,在國內環境下,由於受到Dubbo框架的影響,大部份情況下認為Zookeeper是RPC服務框架下註冊中心最好選擇,隨著Dubbo框架的不斷開發最佳化,和各種註冊中心元件的誕生,即使是RPC框架,現在的註冊中心也逐步放棄了ZooKeeper。在常用的開發集群環境中,ZooKeeper依然起到十分重要的作用,Java體系中,大部份的集群環境都是依賴ZooKeeper管理服務的各個節點。
Zookeeper如何實作註冊中心
Zookeeper可以充當一個服務登錄檔(Service Registry),讓多個服務提供者形成一個集群,讓服務消費者透過服務登錄檔獲取具體的服務存取地址(Ip+埠)去存取具體的服務提供者。如下圖所示:
每當一個服務提供者部署後都要將自己的服務註冊到zookeeper的某一路徑上: /{service}/{version}/{ip:port} 。
比如我們的HelloWorldService部署到兩台機器,那麽Zookeeper上就會建立兩條目錄:
/HelloWorldService/1.0.0/100.19.20.01:16888
/HelloWorldService/1.0.0/100.19.20.02:16888
這麽描述有點不好理解,下圖更直觀:
在zookeeper中,進行服務註冊,實際上就是在zookeeper中建立了一個znode節點,該節點儲存了該服務的IP、埠、呼叫方式(協定、序列化方式)等。該節點承擔著最重要的職責,它由服務提供者(釋出服務時)建立,以供服務消費者獲取節點中的資訊,從而定位到服務提供者真正網路拓撲位置以及得知如何呼叫。
RPC服務註冊/發現過程簡述如下:
服務提供者啟動時,會將其服務名稱,ip地址註冊到配置中心。
服務消費者在第一次呼叫服務時,會透過註冊中心找到相應的服務的IP地址列表,並緩存到本地,以供後續使用。當消費者呼叫服務時,不會再去請求註冊中心,而是直接透過負載均衡演算法從IP列表中取一個服務提供者的伺服器呼叫服務。
當服務提供者的某台伺服器宕機或下線時,相應的ip會從服務提供者IP列表中移除。同時,註冊中心會將新的服務IP地址列表發送給服務消費者機器,緩存在消費者本機。
當某個服務的所有伺服器都下線了,那麽這個服務也就下線了。
同樣,當服務提供者的某台伺服器上線時,註冊中心會將新的服務IP地址列表發送給服務消費者機器,緩存在消費者本機。
服務提供方可以根據服務消費者的數量來作為服務下線的依據。
zookeeper提供了「心跳檢測」功能: 它會定時向各個服務提供者發送一個請求(實際上建立的是一個 socket 長連線),如果長期沒有響應,服務中心就認為該服務提供者已經「掛了」,並將其剔除。
比如100.100.0.237這台機器如果宕機了,那麽zookeeper上的路徑就會只剩/HelloWorldService/1.0.0/100.100.0.238:16888。
Zookeeper的Watch機制其實就是一種 推拉結合的模式 :
服務消費者會去監聽相應路徑(/HelloWorldService/1.0.0),一旦路徑上的數據有任務變化(增加或減少), Zookeeper只會發送一個事件型別和節點資訊給關註的客戶端,而不會包括具體的變更內容 ,所以事件本身是輕量級的,這就是推的部份。
收到變更通知的客戶端需要自己去拉變更的數據 ,這就是拉的部份。
Zookeeper不適合作為註冊中心
作為一個分布式協同服務,ZooKeeper非常好,但是對於Service發現服務來說就不合適了,因為對於Service發現服務來說就算是返回了包含不實的資訊的結果也比什麽都不返回要好。 所以當向註冊中心查詢服務列表時,我們可以容忍註冊中心返回的是幾分鐘以前的註冊資訊,但不能接受服務直接down掉不可用。
但是zk會出現這樣一種情況,當master節點因為網路故障與其他節點失去聯系時,剩余節點會重新進行leader選舉。問題在於,選舉leader的時間太長,30 ~ 120s, 且選舉期間整個zk集群都是不可用的,這就導致在選舉期間註冊服務癱瘓。在雲部署的環境下,因網路問題使得zk集群失去master節點是較大機率會發生的事,雖然服務能夠最終恢復,但是漫長的選舉時間導致的註冊長期不可用是不能容忍的。
所以說, 作為註冊中心,可用性的要求要高於一致性!
在 CAP 模型中, Zookeeper整體遵循一致性(CP)原則 ,即在任何時候對 Zookeeper 的存取請求能得到一致的數據結果,但是當機器下線或者宕機時, 不能保證服務可用性。
那為什麽Zookeeper不使用最終一致性(AP)模型呢?因為這個依賴 Zookeeper的核心演算法是ZAB,所有設計都是為了強一致性 。這個對於分布式協調系統,完全沒沒有毛病,但是 你如果將Zookeeper為分布式協調服務所做的一致性保障,用在註冊中心,或者說服務發現場景,這個其實就不合適。
3.2 Eureka
Eureka 架構圖
什麽,上面這幅圖看起來很復雜?那我給你貼個簡化版:
Eureka 特點
可用性(AP原則) :Eureka 在設計時就緊遵AP原則,Eureka的集群中,只要有一台Eureka還在,就能保證註冊服務可用,只不過查到的資訊可能不是最新的(不保證強一致性)。
去中心化架構 :Eureka Server 可以執行多個例項來構建集群,不同於 ZooKeeper 的選舉 leader 的過程,Eureka Server 采用的是Peer to Peer 對等通訊。這是一種去中心化的架構,無 master/slave 之分,每一個 Peer 都是對等的。節點透過彼此互相註冊來提高可用性,每個節點需要添加一個或多個有效的 serviceUrl 指向其他節點。每個節點都可被視為其他節點的副本。
請求自動切換 :在集群環境中如果某台 Eureka Server 宕機,Eureka Client 的請求會自動切換到新的 Eureka Server 節點上,當宕機的伺服器重新恢復後,Eureka 會再次將其納入到伺服器集群管理之中。
節點間操作復制 :當節點開始接受客戶端請求時,所有的操作都會在節點間進行復制操作,將請求復制到該 Eureka Server 當前所知的其它所有節點中。
自動註冊&心跳 :當一個新的 Eureka Server 節點啟動後,會首先嘗試從鄰近節點獲取所有註冊列表資訊,並完成初始化。Eureka Server 透過 getEurekaServiceUrls() 方法獲取所有的節點,並且會透過心跳契約的方式定期更新。
自動下線 :預設情況下,如果 Eureka Server 在一定時間內沒有接收到某個服務例項的心跳(預設周期為30秒),Eureka Server 將會登出該例項(預設為90秒, eureka.instance.lease-expiration-duration-in-seconds 進行自訂配置)。
保護模式 :當 Eureka Server 節點在短時間內遺失過多的心跳時,那麽這個節點就會進入自我保護模式。
除了上述特點,Eureka還有一種自我保護機制,如果在15分鐘內超過 85% 的節點都沒有正常的心跳,那麽Eureka就認為客戶端與註冊中心出現了網路故障,此時會出現以下幾種情況:
Eureka不再從登錄檔中移除因為長時間沒有收到心跳而過期的服務;
Eureka仍然能夠接受新服務註冊和查詢請求,但是不會被同步到其它節點上(即保證當前節點依然可用)
當網路穩定時,當前例項新註冊的資訊會被同步到其它節點中。
Eureka工作流程
了解完 Eureka 核心概念,自我保護機制,以及集群內的工作原理後,我們來整體梳理一下 Eureka 的工作流程:
Eureka Server 啟動成功,等待伺服端註冊。在啟動過程中如果配置了集群,集群之間定時透過 Replicate 同步登錄檔,每個 Eureka Server 都存在獨立完整的服務登錄檔資訊。
Eureka Client 啟動時根據配置的 Eureka Server 地址去註冊中心註冊服務。
Eureka Client 會每 30s 向 Eureka Server 發送一次心跳請求,證明客戶端服務正常。
當 Eureka Server 90s 內沒有收到 Eureka Client 的心跳,註冊中心則認為該節點失效,會登出該例項。
單位時間內 Eureka Server 統計到有大量的 Eureka Client 沒有上送心跳,則認為可能為網路異常,進入自我保護機制,不再剔除沒有上送心跳的客戶端。
當 Eureka Client 心跳請求恢復正常之後,Eureka Server 自動結束自我保護模式。
Eureka Client 定時全量或者增量從註冊中心獲取服務登錄檔,並且將獲取到的資訊緩存到本地。
服務呼叫時,Eureka Client 會先從本地緩存找尋調取的服務。如果獲取不到,先從註冊中心重新整理登錄檔,再同步到本地緩存。
Eureka Client 獲取到目標伺服器資訊,發起服務呼叫。
Eureka Client 程式關閉時向 Eureka Server 發送取消請求,Eureka Server 將例項從登錄檔中刪除。
透過分析 Eureka 工作原理,我可以明顯地感覺到 Eureka 的設計之巧妙,完美地解決了註冊中心的穩定性和高可用性。
Eureka 為了保障註冊中心的高可用性,容忍了數據的非強一致性,服務節點間的數據可能不一致, Client-Server 間的數據可能不一致。 比較適合跨越多機房、對註冊中心服務可用性要求較高的使用場景。
3.3 Nacos
以下內容摘抄自Nacos官網:https://nacos.io/zh-cn/docs/what-is-nacos.html
Nacos 致力於幫助您發現、配置和管理微服務。Nacos 提供了一組簡單易用的特性集,幫助您快速實作動態服務發現、服務配置、服務後設資料及流量管理。
Nacos 幫助您更敏捷和容易地構建、交付和管理微服務平台。Nacos 是構建以「服務」為中心的現代套用架構 (例如微服務範式、雲原生範式) 的服務基礎設施。
Nacos 主要特點
服務發現和服務健康監測 :
Nacos 支持基於 DNS 和基於 RPC 的服務發現。服務提供者使用原生SDK、OpenAPI、或一個獨立的Agent TODO註冊 Service 後,服務消費者可以使用DNS TODO 或HTTP&API尋找和發現服務。
Nacos 提供對服務的即時的健康檢查,阻止向不健康的主機或服務例項發送請求。Nacos 支持傳輸層 (PING 或 TCP)和套用層 (如 HTTP、MySQL、使用者自訂)的健康檢查。對於復雜的雲環境和網路拓撲環境中(如 VPC、邊緣網路等)服務的健康檢查,Nacos 提供了 agent 上報模式和伺服端主動檢測2種健康檢查模式。Nacos 還提供了統一的健康檢查儀表盤,幫助您根據健康狀態管理服務的可用性及流量。
動態配置服務 :
動態配置服務可以讓您以中心化、外部化和動態化的方式管理所有環境的套用配置和服務配置。
動態配置消除了配置變更時重新部署套用和服務的需要,讓配置管理變得更加高效和敏捷。
配置中心化管理讓實作無狀態服務變得更簡單,讓服務按需彈性擴充套件變得更容易。
Nacos 提供了一個簡潔易用的UI (控制台樣例 Demo) 幫助您管理所有的服務和套用的配置。Nacos 還提供包括配置版本跟蹤、金絲雀釋出、一鍵回滾配置以及客戶端配置更新狀態跟蹤在內的一系列開箱即用的配置管理特性,幫助您更安全地在生產環境中管理配置變更和降低配置變更帶來的風險。
動態 DNS 服務 :
動態 DNS 服務支持權重路由,讓您更容易地實作中間層負載均衡、更靈活的路由策略、流量控制以及數據中心內網的簡單DNS解析服務。動態DNS服務還能讓您更容易地實作以 DNS 協定為基礎的服務發現,以幫助您消除耦合到廠商私有服務發現 API 上的風險。
Nacos 提供了一些簡單的 DNS APIs TODO 幫助您管理服務的關聯網域名稱和可用的 IP:PORT 列表。
小節一下:
Nacos是阿裏開源的,支持基於 DNS 和基於 RPC 的服務發現。
Nacos的註冊中心支持CP也支持AP ,對他來說只是一個命令的切換,隨你玩,還支持各種註冊中心遷移到Nacos,反正一句話,只要你想要的他就有。
Nacos除了服務的註冊發現之外,還支持動態配置服務 ,一句話概括就是 Nacos = Spring Cloud註冊中心 + Spring Cloud配置中心 。
3.4 Consul
Consul 是 HashiCorp 公司推出的開源工具,用於實作分布式系統的服務發現與配置。與其它分布式服務註冊與發現的方案,Consul 的方案更「一站式」,內建了服務註冊與發現框 架、分布一致性協定實作、健康檢查、Key/Value 儲存、多數據中心方案,不再需要依賴其它工具(比如 ZooKeeper 等)。
Consul 使用起來也較為簡單,使用 Go 語言編寫,因此具有天然可移植性(支持Linux、windows和Mac OS X);安裝包僅包含一個可執行檔,方便部署,與 Docker 等輕量級容器可無縫配合。
Consul 的呼叫過程
當 Producer 啟動的時候,會向 Consul 發送一個 post 請求,告訴 Consul 自己的 IP 和 Port;
Consul 接收到 Producer 的註冊後,每隔 10s(預設)會向 Producer 發送一個健康檢查的請求,檢驗 Producer 是否健康;
當 Consumer 發送 GET 方式請求 /api/address 到 Producer 時,會先從 Consul 中拿到一個儲存服務 IP 和 Port 的臨時表,從表中拿到 Producer 的 IP 和 Port 後再發送 GET 方式請求 /api/address;
該臨時表每隔 10s 會更新,只包含有透過了健康檢查的 Producer。
Consul 主要特征
CP模型,使用 Raft 演算法來保證強一致性,不保證可用性;
支持服務註冊與發現、健康檢查、KV Store功能。
支持多數據中心,可以避免單數據中心的單點故障,而其部署則需要考慮網路延遲, 分片等情況等。
支持安全服務通訊,Consul可以為服務生成和分發TLS證書,以建立相互的TLS連線。
支持 http 和 dns 協定介面;
官方提供 web 管理界面。
多數據中心
Consul支持開箱即用的多數據中心,這意味著使用者不需要擔心需要建立額外的抽象層讓業務擴充套件到多個區域。
在上圖中有兩個DataCenter,他們透過Internet互聯,同時請註意為了提高通訊效率,只有Server節點才加入跨數據中心的通訊。
在單個數據中心中,Consul分為Client和Server兩種節點(所有的節點也被稱為Agent),Server節點保存數據,Client負責健康檢查及轉發數據請求到Server;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埠完成。
3.5 ETCD
etcd是一個Go言編寫的分布式、高可用的一致性鍵值儲存系統,用於提供可靠的分布式鍵值儲存、配置共享和服務發現等功能。
ETCD 特點
易使用:基於HTTP+JSON的API讓你用curl就可以輕松使用;
易部署:使用Go語言編寫,跨平台,部署和維護簡單;
強一致:使用Raft演算法充分保證了分布式系統數據的強一致性;
高可用:具有容錯能力,假設集群有n個節點,當有(n-1)/2節點發送故障,依然能提供服務;
持久化:數據更新後,會透過WAL格式數據持久化到磁盤,支持Snapshot快照;
快速:每個例項每秒支持一千次寫操作,極限寫效能可達10K QPS;
安全:可選SSL客戶認證機制;
ETCD 3.0:除了上述功能,還支持gRPC通訊、watch機制。
ETCD 框架
etcd主要分為四個部份:
HTTP Server:用於處理使用者發送的API請求以及其它etcd節點的同步與心跳資訊請求。
Store:用於處理etcd支持的各類功能的事務,包括數據索引、節點狀態變更、監控與反饋、事件處理與執行等等,是etcd對使用者提供的大多數API功能的具體實作。
Raft:Raft強一致性演算法的具體實作,是etcd的核心。
WAL:Write Ahead Log(預寫式日誌),是etcd的數據儲存方式。除了在記憶體中存有所有數據的狀態以及節點的索引以外,etcd就透過WAL進行持久化儲存。WAL中,所有的數據送出前都會事先記錄日誌。Snapshot是為了防止數據過多而進行的狀態快照;Entry表示儲存的具體日誌內容。
通常,一個使用者的請求發送過來,會經由HTTP Server轉發給Store進行具體的事務處理,如果涉及到節點的修改,則交給Raft模組進行狀態的變更、日誌的記錄,然後再同步給別的etcd節點以確認數據送出,最後進行數據的送出,再次同步。
04 註冊中心對比&選型
4.1 註冊中心對比
服務健康檢查 :Euraka 使用時需要顯式配置健康檢查支持;Zookeeper、Etcd 則在失去了和服務行程的連線情況下任務不健康,而 Consul 相對更為詳細點,比如記憶體是否已使用了90%,檔案系統的空間是不是快不足了。
多數據中心 :Consul 和 Nacos 都支持,其他的產品則需要額外的開發工作來實作。
KV 儲存服務 :除了 Eureka,其他幾款都能夠對外支持 k-v 的儲存服務,所以後面會講到這幾款產品追求高一致性的重要原因。而提供儲存服務,也能夠較好的轉化為動態配置服務哦。
CAP 理論的取舍 :
Eureka 是典型的 AP,Nacos可以配置為 AP,作為分布式場景下的服務發現的產品較為合適,服務發現場景的可用性優先級較高,一致性並不是特別致命。
而Zookeeper、Etcd、Consul則是 CP 型別犧牲可用性,在服務發現場景並沒太大優勢;
Watch的支持 :Zookeeper 支持伺服器端推播變化,其它都透過長輪詢的方式來實作變化的感知。
自身集群的監控 :除了Zookeeper和Nacos,其它幾款都預設支持 metrics,運維者可以搜集並報警這些度量資訊達到監控目的。
Spring Cloud的整合 :目前都有相對應的 boot starter,提供了整合能力。
4.2 註冊中心選型
關於註冊中心的對比和選型,其實上面已經講的非常清楚了,我給出一些個人理解:
關於CP還是AP的選擇 :選擇 AP,因為可用性高於一致性,所以更傾向 Eureka 和 Nacos;關於Eureka、Nacos如何選擇,哪個讓我做的事少,我就選擇哪個,顯然 Nacos 幫我們做了更多的事。
技術體系 :Etcd 和 Consul 都是Go開發的,Eureka、Nacos、Zookeeper 和 Zookeeper 都是Java開發的,可能計畫屬於不同的技術棧,會偏向選擇對應的技術體系。
高可用 :這幾款開源產品都已經考慮如何搭建高可用集群,有些差別而已;
產品的活躍度 :這幾款開源產品整體上都比較活躍。
如喜歡本文,請點選右上角,把文章分享到朋友圈
如有想了解學習的技術點,請留言給若飛安排分享
因公眾號更改推播規則,請點「在看」並加「星標」 第一時間獲取精彩技術分享
·END·
相關閱讀:
作者:樓仔
來源:樓仔
版權申明:內容來源網路,僅供學習研究,版權歸原創者所有。如有侵權煩請告知,我們會立即刪除並表示歉意。謝謝!
架構師
我們都是架構師!
關註 架構師(JiaGouX),添加「星標」
獲取每天技術幹貨,一起成為牛逼架構師
技術群請 加若飛: 1321113940 進架構師群
投稿、合作、版權等信箱: [email protected]