還在用 Zookeeper 作為註冊中心?小心坑死你!
大家好,我是樓仔呀。
這篇文章對 Zookeeper 的註冊中心原理再深入研究一下,主要學習它的設計思想。
直接上文章目錄:
1. 基本概念
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 註冊中心需要實現功能
根據註冊中心原理的描述,註冊中心必須實現以下功能,偷個懶,直接貼幅圖:
2. ZK 註冊中心原理
Zookeeper 可以充當一個服務登錄檔(Service Registry),讓多個服務提供者形成一個叢集,讓服務消費者透過服務登錄檔獲取具體的服務訪問地址(Ip + 埠)去訪問具體的服務提供者。
2.1 ZK 註冊流程
每當一個服務提供者部署後都要將自己的服務註冊到 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 地址列表傳送給服務消費者機器,快取在消費者本機。 服務提供方可以根據服務消費者的數量來作為服務下線的依據。
2.2 ZK 的心跳檢測
問題:第 3 步中“當服務提供者的某臺伺服器當機或下線時”,Zookeeper 如何感知到呢?
Zookeeper 提供了“心跳檢測”功能,它會定時向各個服務提供者傳送一個請求(實際上建立的是一個 socket 長連線),如果長期沒有響應,服務中心就認為該服務提供者已經“掛了”,並將其剔除。
比如 100.100.0.237 這臺機器如果當機了,那麼 Zookeeper 上的路徑就會只剩 /HelloWorldService/1.0.0/100.100.0.238:16888。
2.3 ZK 的 Watch 機制
問題:第 3 步和第 5 步中“註冊中心會將新的服務 IP 地址列表傳送給服務消費者機器”,這步是如何實現的呢?
這個問題也是經典的生產者-消費者問題,解決的方式有兩種:
主動拉取策略:服務的消費者定期呼叫註冊中心提供的服務獲取介面獲取最新的服務列表並更新本地快取,經典案例就是 Eureka。
釋出-訂閱模式:服務消費者能夠實時監控服務更新狀態,通常採用監聽器以及回撥機制。
Zookeeper 使用的是“釋出-訂閱模式”,這裡就要提到 Zookeeper 的 Watch 機制,整體流程如下:
客戶端先向 ZooKeeper 服務端成功註冊想要監聽的節點狀態,同時客戶端本地會儲存該監聽器相關的資訊在 WatchManager 中; 當 ZooKeeper 服務端監聽的資料狀態發生變化時,ZooKeeper 就會主動通知傳送相應事件資訊給相關會話客戶端,客戶端就會在本地響應式的回撥相關 Watcher 的 Handler。
上面講的有點抽象,大白話解讀一下,Zookeeper 的 Watch 機制其實就是一種推拉結合的模式:
服務消費者會去監聽相應路徑(/HelloWorldService/1.0.0),一旦路徑上的資料有任務變化(增加或減少),Zookeeper 只會傳送一個事件型別和節點資訊給關注的客戶端,而不會包括具體的變更內容,所以事件本身是輕量級的,這就是推的部分。 收到變更通知的客戶端需要自己去拉變更的資料,這就是拉的部分。
3. ZK 是否適合作為註冊中心
探討這個問題前,我們一定需要知道什麼是 CAP 理論。
3.1 CAP 理論
CAP 理論是分散式架構中重要理論:
一致性(Consistency):所有節點在同一時間具有相同的資料; 可用性(Availability) :保證每個請求不管成功或者失敗都有響應; 分隔容忍(Partition tolerance) :系統中任意資訊的丟失或失敗不會影響系統的繼續運作。
關於 P 的理解,我覺得是在整個系統中某個部分,掛掉了,或者當機了,並不影響整個系統的運作或者說使用,而可用性是,某個系統的某個節點掛了,但是並不影響系統的接受或者發出請求。
CAP 不可能都取,只能取其中 2 個的原因如下:
如果 C 是第一需求的話,那麼會影響A的效能,因為要資料同步,不然請求結果會有差異,但是資料同步會消耗時間,期間可用性就會降低。 如果 A 是第一需求,那麼只要有一個服務在,就能正常接受請求,但是對與返回結果變不能保證,原因是,在分散式部署的時候,資料一致的過程不可能想切線路那麼快。 再如果,同時滿足一致性和可用性,那麼分割槽容錯就很難保證了,也就是單點,也是分散式的基本核心。
3.2 ZK 作為註冊中心探討
作為一個分散式協同服務,ZooKeeper 非常好,但是對於 Service 發現服務來說就不合適了,因為對於 Service 發現服務來說就算是返回了包含不實的資訊的結果也比什麼都不返回要好。
所以當向註冊中心查詢服務列表時,我們可以容忍註冊中心返回的是幾分鐘以前的註冊資訊,但不能接受服務直接 down 掉不可用。
但是 zk 會出現這樣一種情況,當 master 節點因為網路故障與其他節點失去聯絡時,剩餘節點會重新進行 leader 選舉。問題在於,選舉 leader 的時間太長,30 ~ 120s,且選舉期間整個zk叢集都是不可用的,這就導致在選舉期間註冊服務癱瘓。
在雲部署的環境下,因網路問題使得 zk 叢集失去 master 節點是較大機率會發生的事,雖然服務能夠最終恢復,但是漫長的選舉時間導致的註冊長期不可用是不能容忍的。
所以說,作為註冊中心,可用性的要求要高於一致性!
在 CAP 模型中,Zookeepe 整體遵循一致性(CP)原則,即在任何時候對 Zookeeper 的訪問請求能得到一致的資料結果,但是當機器下線或者當機時,不能保證服務可用性。
那為什麼 Zookeeper 不使用最終一致性(AP)模型呢?因為這個依賴 Zookeeper 的核心演算法是 ZAB,所有設計都是為了強一致性。這個對於分散式協調系統,完全沒沒有毛病,但是你如果將 Zookeeper為分散式協調服務所做的一致性保障,用在註冊中心,或者說服務發現場景,這個其實就不合適。
4. 小節
我們對 Zookeeper 的註冊中心總結如下:
Zookeeper 的心跳檢測,可以自動探測服務提供者機器的當機或下線; Zookeeper 的 Watch 機制,可以將變更的註冊列表推給服務消費者; Zookeeper 是 CP 模型,不太適合作為註冊中心。
不過網上也有說,Zookeeper 目前已經支援 AP,準確說是 AP + Base 最終一致性,可以和我一起討論哈。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024923/viewspace-2930885/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- SpringCloud之使用Zookeeper作為註冊中心SpringGCCloud
- Dubbo:Nacos作為註冊中心
- gRPC 註冊中心,常用的註冊中心你懂了?AP 還是 CP (七)RPC
- 介紹如何在Spring Cloud中使用Zookeeper作為服務註冊中心SpringCloud
- SpringCloud用zookeeper做註冊中心SpringGCCloud
- Dubbo 中 Zookeeper 註冊中心原理分析
- Rpc-實現Zookeeper註冊中心RPC
- Dubbo使用nacos作為註冊中心原理剖析
- Spring Cloud Alibaba:Nacos 作為註冊中心和配置中心使用SpringCloud
- 【GoLang 那點事】gRPC 註冊中心,常用的註冊中心你懂了嗎?AP 還是 CP(七)GolangRPC
- SpringBoot使用Nacos作為配置中心服務和服務註冊中心Spring Boot
- Dubbo與SpringCloud Alibaba使用Nacos作為配置中心和註冊中心SpringGCCloud
- 為什麼阿里的dubbo註冊中心要放棄zookeeper, 而用Nacos?阿里
- Spring Cloud Alibaba 使用Nacos作為服務註冊中心SpringCloud
- Spring Cloud 部署時如何使用 Kubernetes 作為註冊中心和配置中心SpringCloud
- @Async註解的坑,小心
- SpringBoot與Dubbo整合報錯排查(Nacos作為註冊中心)Spring Boot
- consul 作為服務註冊與發現和配置中心
- naocs 作為服務註冊與發現和配置中心
- 構建dubbo分散式平臺-window安裝zookeeper註冊中心分散式
- Eureka註冊中心
- 註冊中心-consul
- 註冊中心consul
- Apache Dubbo 原始碼搭建與解讀(八)—— Dubbo 註冊中心之ZooKeeperApache原始碼
- Spring Cloud 升級之路 - 2020.0.x - 4. 使用 Eureka 作為註冊中心SpringCloud
- #Java裡你還在用double作為價格的欄位型別?你犯了大錯了!Java型別
- 【SpringCloud】consul註冊中心註冊的服務為內網(區域網)IPSpringGCCloud內網
- 構建springmvc+myabtis+dubbo分散式平臺-zookeeper註冊中心安裝SpringMVC分散式
- Dubbo系列之 (二)Registry註冊中心-註冊(1)
- Dubbo系列之 (二)Registry註冊中心-註冊(2)
- springcloud-註冊中心和配置中心SpringGCCloud
- 微服務框架/配置中心/註冊中心微服務框架
- 你還在用if-else嗎?
- SpringCloud整合Consul註冊中心SpringGCCloud
- springcloud(二):註冊中心EurekaSpringGCCloud
- Dubbo使用Nacos註冊中心
- consul 服務註冊中心
- 【SpringBoot】服務對註冊中心的註冊時機Spring Boot