從0開始學微服務:13 開源服務註冊中心如何選型?

從0開始學微服務:13 開源服務註冊中心如何選型?

上一期我給你講了服務註冊中心的落地實踐,以及在實際應用中可能會遇到的問題和對應的解決方案。關於註冊中心,如果你的團隊有足夠的人才和技術儲備,可以選擇自己研發註冊中心。但對於大多數中小規模團隊來說,我的建議是最好使用業界開源的、應用比較成熟的註冊中心解決方案,把精力投入到業務架構的改造中,不要自己造輪子。

當下主流的服務註冊與發現的解決方案,主要有兩種:

  • 應用內註冊與發現:註冊中心提供服務端和客戶端的 SDK,業務應用通過引入註冊中心提供的 SDK,通過 SDK 與註冊中心交互,來實現服務的註冊和發現。
  • 應用外註冊與發現:業務應用本身不需要通過 SDK 與註冊中心打交道,而是通過其他方式與註冊中心交互,間接完成服務註冊與發現。

下面我會用兩個業界使用比較成熟的註冊中心開源實現,來講解下應用內和應用外兩種解決方案的不同之處。

兩種典型的註冊中心實現

1. 應用內

採用應用內註冊與發現的方式,最典型的案例要屬 Netflix 開源的 Eureka,官方架構圖如下。

從0開始學微服務:13 開源服務註冊中心如何選型?

對著這張圖,我來介紹下 Eureka 的架構,它主要由三個重要的組件組成:

  • Eureka Server:註冊中心的服務端,實現了服務信息註冊、存儲以及查詢等功能。
  • 服務端的 Eureka Client:集成在服務端的註冊中心 SDK,服務提供者通過調用 SDK,實現服務註冊、反註冊等功能。
  • 客戶端的 Eureka Client:集成在客戶端的註冊中心 SDK,服務消費者通過調用 SDK,實現服務訂閱、服務更新等功能。

2. 應用外

採用應用外方式實現服務註冊和發現,最典型的案例是開源註冊中心 Consul,它的架構圖如下。

從0開始學微服務:13 開源服務註冊中心如何選型?

通過這張架構圖,可以看出來使用 Consul 實現應用外服務註冊和發現主要依靠三個重要的組件:

  • Consul:註冊中心的服務端,實現服務註冊信息的存儲,並提供註冊和發現服務。
  • Registrator:一個開源的第三方服務管理器項目,它通過監聽服務部署的 Docker 實例是否存活,來負責服務提供者的註冊和銷燬。
  • Consul Template:定時從註冊中心服務端獲取最新的服務提供者節點列表並刷新 LB 配置(比如 Nginx 的 upstream),這樣服務消費者就通過訪問 Nginx 就可以獲取最新的服務提供者信息。

對比小結一下,這兩種解決方案的不同之處在於應用場景,應用內的解決方案一般適用於服務提供者和服務消費者同屬於一個技術體系;應用外的解決方案一般適合服務提供者和服務消費者採用了不同技術體系的業務場景,比如服務提供者提供的是 C++ 服務,而服務消費者是一個 Java 應用,這時候採用應用外的解決方案就不依賴於具體一個技術體系。同時,對於容器化後的雲應用來說,一般不適合採用應用內 SDK 的解決方案,因為這樣會侵入業務,而應用外的解決方案正好能夠解決這個問題。

註冊中心選型要考慮的兩個問題

在選擇註冊中心解決方案的時候,除了要考慮是採用應用內註冊還是應用外註冊的方式以外,還有兩個最值得關注的問題,一個是高可用性,一個是數據一致性,下面我來給你詳細解釋下為什麼。

1. 高可用性

註冊中心作為服務提供者和服務消費者之間溝通的紐帶,它的高可用性十分重要。試想,如果註冊中心不可用了,那麼服務提供者就無法對外暴露自己的服務,而服務消費者也無法知道自己想要調用的服務的具體地址,後果將不堪設想。

根據我過往的實踐經驗,實現高可用性的方法主要有兩種:

  • 集群部署,顧名思義就是通過部署多個實例組成集群來保證高可用性,這樣的話即使有部分機器宕機,將訪問遷移到正常的機器上就可以保證服務的正常訪問。
  • 多 IDC 部署,就是部署在不止一個機房,這樣能保證即使一個機房因為斷電或者光纜被挖斷等不可抗力因素不可用時,仍然可以通過把請求遷移到其他機房來保證服務的正常訪問。

我們以 Consul 為例,來看看它是如何通過這兩種方法來保證註冊中心的高可用性。

從下面的官方架構圖中你可以看到,一方面,在每個數據中心(DATACENTER)內都有多個註冊中心 Server 節點可供訪問;另一方面還可以部署在多個數據中心來保證多機房高可用性。

從0開始學微服務:13 開源服務註冊中心如何選型?

2. 數據一致性

為了保證註冊中心的高可用性,註冊中心的部署往往都採用集群部署,並且還通常部署在不止一個數據中心,這樣的話就會引出另一個問題,多個數據中心之間如何保證數據一致?如何確保訪問數據中心中任何一臺機器都能得到正確的數據?

這裡就涉及分佈式系統中著名的 CAP 理論,即同時滿足一致性、可用性、分區容錯性這三者是不可能的,其中 C(Consistency)代表一致性,A(Availability)代表可用性,P(Partition Tolerance)代表分區容錯性。

為什麼說 CAP 三者不能被同時滿足的呢?

你可以想象在一個分佈式系統裡面,包含了多個節點,節點之間通過網絡連通在一起。正常情況下,通過網絡,從一個節點可以訪問任何別的節點上的數據。

但是有可能出現網絡故障,導致整個網絡被分成了互不連通的區域,這就叫作分區。一旦出現分區,那麼一個區域內的節點就沒法訪問其他節點上的數據了,最好的辦法是把數據複製到其他區域內的節點,這樣即使出現分區,也能訪問任意區域內節點上的數據,這就是分區容錯性。

但是把數據複製到多個節點就可能出現數據不一致的情況,這就是一致性。要保證一致,就必須等待所有節點上的數據都更新成功才可用,這就是可用性。

總的來說,就是數據節點越多,分區容錯性越高,但數據一致性越難保證。為了保證數據一致性,又會帶來可用性的問題。

而註冊中心一般採用分佈式集群部署,也面臨著 CAP 的問題,根據 CAP 不能同時滿足,所以不同的註冊中心解決方案選擇的方向也就不同,大致可分為兩種。

  • CP 型註冊中心,犧牲可用性來保證數據強一致性,最典型的例子就是 ZooKeeper,etcd,Consul 了。ZooKeeper 集群內只有一個 Leader,而且在 Leader 無法使用的時候通過 Paxos 算法選舉出一個新的 Leader。這個 Leader 的目的就是保證寫信息的時候只向這個 Leader 寫入,Leader 會同步信息到 Followers,這個過程就可以保證數據的強一致性。但如果多個 ZooKeeper 之間網絡出現問題,造成出現多個 Leader,發生腦裂的話,註冊中心就不可用了。而 etcd 和 Consul 集群內都是通過 raft 協議來保證強一致性,如果出現腦裂的話, 註冊中心也不可用。
  • AP 型註冊中心,犧牲一致性來保證可用性,最典型的例子就是 Eureka 了。對比下 Zookeeper,Eureka 不用選舉一個 Leader,每個 Eureka 服務器單獨保存服務註冊地址,因此有可能出現數據信息不一致的情況。但是當網絡出現問題的時候,每臺服務器都可以完成獨立的服務。

而對於註冊中心來說,最主要的功能是服務的註冊和發現,在網絡出現問題的時候,可用性的需求要遠遠高於數據一致性。即使因為數據不一致,註冊中心內引入了不可用的服務節點,也可以通過其他措施來避免,比如客戶端的快速失敗機制等,只要實現最終一致性,對於註冊中心來說就足夠了。因此,選擇 AP 型註冊中心,一般更加合適。

總結

總的來說,在選擇開源註冊中心解決方案的時候,要看業務的具體場景。

  • 如果你的業務體系都採用 Java 語言的話,Netflix 開源的 Eureka 是一個不錯的選擇,並且它作為服務註冊與發現解決方案,能夠最大程度的保證可用性,即使出現了網絡問題導致不同節點間數據不一致,你仍然能夠訪問 Eureka 獲取數據。
  • 如果你的業務體系語言比較複雜,Eureka 也提供了 Sidecar 的解決方案;也可以考慮使用 Consul,它支持了多種語言接入,包括 Go、Python、PHP、Scala、Java,Erlang、Ruby、Node.js、.NET、Perl 等。
  • 如果你的業務已經是雲原生的應用,可以考慮使用 Consul,搭配 Registrator 和 Consul Template 來實現應用外的服務註冊與發現。

思考題

針對你的業務場景,如果要選擇一種開源註冊中心實現的話,你覺得哪種方案更適合?

歡迎你在留言區寫下自己的思考,與我一起討論。


分享到:


相關文章: