我們做出了一個分佈式註冊中心

開篇

這篇文章是基於 SOFA Meetup 合肥站的分享總結,主要針對於註冊中心的定位以及功能介紹,通過對螞蟻註冊中心發展史的分析,帶領大家瞭解,螞蟻的註冊中心是如何一步一步演變爲現在的規模和特性的。

更多深入的技術細節,歡迎大家加入到 SOFA 和 SOFARegistry 的社區中,探尋結果。

註冊中心是什麼

一、服務發現 & 服務註冊

註冊中心簡單來說,是爲了解決分佈式場景下,服務之間互相發現的問題。

如下圖所示,服務 A 想要調用服務 B 的時候,需要知道 B 的地址在哪裏,如何解決這個問題?

一般來說,分爲兩個點:

  1. 服務發現可以有一箇中心化的組件或者說是存儲,它承載了所有服務的地址,同時提供出來一個可供查詢和訂閱的能力,服務的消費方可以通過和這個中心化的存儲交互,獲取服務提供方的地址列表。

  2. 服務註冊:同樣是上文中中心化的組件,但是,這個時候的服務信息可以有兩種措施:

二、調用流程

如上圖所示,就是目前一種主流的註冊中心模式,SOFARegistry 和 Nacos 都是這種模式。

  1. 服務 A,服務 B 通過 SDK 或者 REST 將自身的服務信息上報給註冊中心;

  2. 服務 A 需要調用服務 B 的時候,就對註冊中心發起請求,拉取和服務 B 相關的服務 IP 列表以及信息;

  3. 在獲取到服務 B 的列表之後,就可以通過自身定義的負載均衡算法訪問服務 B。

三、心跳

心跳是註冊中心用於解決服務不可用時,及時拉出服務降低影響的默認方式,如下圖所示。

  1. 服務 B 的一個節點斷網或是 hang 住,引發心跳超時;或是宕機、斷鏈直接引發心跳失敗;

  2. 註冊中心把問題節點從自身的存儲中拉出(這裏拉出根據具體實現:有的是直接刪除,有的是標記爲不健康);

  3. 服務 A 收到註冊中心的通知,獲取到服務 B 最新的列表。

四、Dubbo 註冊中心

下面通過 Dubbo 的例子,我們來看一下注冊中心是如何使用的,以及流程:首先,Dubbo 在 2.7 和 3.0 中的配置略有不同,但是都是簡單易懂的,這裏都放上來。

Dubbo-2.7

Dubbo-3.0

在 RPC 客戶端只需要配置一個註冊中心的地址即可,地址中包含了基礎三元素:

  1. protocol(協議類型)比如,zookeeper;

  2. host;

  3. port。

基於此,Dubbo 的註冊流程如下圖所示:

  1. 服務的生產方通過 Dubbo 客戶端向註冊中心(Registry)發起註冊行爲(register);

  2. 服務的消費方通過 Dubbo 客戶端訂閱信息(subscribe);

  3. 註冊中心通過通知的方式,下發服務列表給服務消費方。

五、註冊中心的本質

通過前文的講解,以及 Dubbo 組件的具體例子,我們大概可以歸納註冊中心的本質。

“存儲” + “可運維”

  1. 一方面,註冊中心需要存儲能力去記錄服務的信息,比如應用列表;

  2. 另一方面,註冊中心在實踐過程中,需要提供必需的運維手段,比如關閉某一服務流量。

螞蟻註冊中心編年史

一、史前時代

史前時代的螞蟻是相當久遠的架構,當時所有的服務部署在同一臺物理機上或者 JVM 上,服務之間不存在有跨機器調用的場景,這裏略過不表述。

二、硬負載時代

後來,爲了解決應用之間的耦合帶來的部署難,運維難問題,我們對服務進行了拆分,拆分後的服務,遇到了一個問題,就是如何處理服務之間的調用關係,這個時候,螞蟻用了兩種硬負載 F5 或是 LVS。

通過簡單的 4 層代理,我們可以把服務部署在代理的後面,服務與服務之間通過代理互相訪問,達到了跨機調用的目的。

三、第一代註冊中心 -- 硬負載到軟負載的演變

通過硬負載訪問的方式,一方面解決了服務之間互相調用的問題,部署架構也簡單易懂;另一方面,在業務快速增長之後,卻帶來了一定的問題:

  1. 單點的問題(所有調用都走 F5 的話,F5 一旦掛了,很多服務會不可用);

  2. 容量問題(F5 承載的流量太高,本身會到一個性能瓶頸)。

這個時候,螞蟻引進了阿里集團的一款產品叫 ConfigServer,作爲註冊中心進行使用,這個註冊中心的架構就和開頭提到的架構很像了,服務之間可以通過 IP 直接訪問,而降低了對負載均衡產品的強依賴,減少了單點風險。

四、第二代註冊中心 -- ScaleUp?ScaleOut?It's a problem

但是,問題還在持續,那就是註冊中心,本身是一個單點,那麼,他就會繼續遇到上文中所說的兩個問題:

  1. 單點風險(註冊中心本身是單機應用);

  2. 容量瓶頸(單臺註冊中心的連接數和存儲數據的容量是有限的)。

解決的方式有兩種:

  1. scale-up(淘寶):通過增加機器的配置,來增強容量以及扛鏈接能力;同時,通過主 - 備這樣的架構,來保障可用性;

  2. scale-out(螞蟻):通過分片機制,將數據和鏈接均勻分佈在多個節點上,做到水平拓展;通過分片之後的備份,做到高可用。

螞蟻和淘寶走了兩條不同的路,也推進了螞蟻后面演進出一套獨立的生態系統。

螞蟻的演進架構如下,產生了兩種不同的應用節點:

  1. Session 節點,專門用來抗鏈接使用,本身無狀態可以快速擴展,單機對資源的佔用很小;

  2. Data 節點,專門用來存儲數據,通過分片的方式降低單個節點的存儲量,控制資源佔用。

五、第五代註冊中心 -- Meta 節點的誕生

上面的架構已經很符合目前主流的分佈式架構了,但是在運維過程中,產生了一系列問題,比如:

  1. 所有 Data 都是分佈式的,Data 之間的服務發現需要通過啓動時給定一個配置文件,這樣就和標準運維脫鉤;

  2. Data 節點的上下線需要去及時修改配置文件,否則集羣重啓會受到影響;

  3. 分佈式存儲一致性問題,每次迭代發佈,需要鎖定 paas 平臺,防止節點變動帶來的不一致。

所有這些問題的產生,我們發現可以引入一個元數據管理中心(Meta)節點來,解決對 Data 和 Session 管理的問題,Data 和 Session 通過 4 層負載或是 7 層負載對 Meta 訪問即可。

對比業界的解決方案,都有類似的模型,比如 HDFS 的 Name Node、Kafka 依賴於 ZK,Oceanbase 依賴於 RootServer 或者配置中心 Apollo 依賴於 Euraka。

Meta 節點的出現,緩解了手工運維註冊中心的瓶頸,但是,依然沒有從根本上解決問題,那麼問題在哪裏?詳見下文分析。

六、第六代註冊中心 -- 面向運維的註冊中心

上文說道,Meta 節點的出現,承接了 Data 以及 Session 之間服務發現的問題,但是,叢雲未測來講,還是有很多問題解決不了,比如:

  1. Data 節點的發佈在數據量大的前提下,依然是個痛點;

  2. Session 節點的新加節點上,可能很久都沒有流量。

等等,對於這些問題,在 SOFARegistry 5.x 的基礎上,我們快速迭代了 6.0 版本,主要是面向運維的註冊中心。

Data 節點發布難的問題,說到底是一個影響範圍的問題,如何控制單一 Data 節點發布或者掛掉對數據的影響面,是解決問題的本源,這裏我們採用了兩個措施:

  1. 改進數據存儲算法(consistent-hash -> hash-slot);

  2. 應用級服務發現。

(1)存儲算法的演進

之前我們使用了一致性 hash 的算法,如下圖所示,每一個節點承載一部分數據,通過是存儲進行 hash 運算,算出存儲內容的 hash 值,再計算出 hash 值落在哪一個 Data 所負責的存儲區間,來存儲數據。

當 Data 節點宕機或者重啓時,由下一個 Data 節點接收宕機節點的數據以及數據的訪問支持。

這樣依賴,數據遷移的粒度只能以單個 Data 節點所存儲的數據爲單位,在數據量較大(單節點 8G)的情況下,對數據的重建有一定的影響,而且,在 Data 連續宕機的情況下,可能存在數據丟失或是不一致的場景。

改進後的算法,我們參考了 Redis Cluster 的算法機制,使用 hash slot 進行數據分片;

這樣,在 Data 發佈過程中,可以控制數據的遷移以 slot 爲單位(單個 Data 節點多個 slot,可配置)

同時,爲了解決遷移或是宕機期間,數據寫入不一致的場景,我們引入了數據回放的補償機制,Data 在 promotion 爲 slot 的 master 之後,會主動地去和所有的 Session 完成一次數據比對 / 校驗,增量同步新增數據。

(2)應用級服務發現

應用級服務發現是爲了解決數據存儲量大的問題,因爲篇幅原因,這裏略過不表述。

開源

SOFARegistry 從項目早期就開始了開源的進程,與目前主流的註冊中心的對比如下:

我們認爲,註冊中心首先需要解決的是可用性的問題,所以,在分佈式一致性的問題上,我們選擇了 AP 的模型,這點也和主流的註冊中心,例如 Euraka 以及 Nacos 保持一致的觀點。

其次,在性能方面,基於長連接的 SOFARegistry 擁有更短的推送延遲,相較於 Nacos 1.0 的推送時延更短(Nacos 1.0 基於 Long Polling 的模型,Nacos 2.0 也使用了長連接的模型)。

在協議方面,SOFARegistry 使用了螞蟻開源協議棧:BOLT 協議(類似於 HTTP 2.0)的流式協議,更加輕量級,同時協議本身的全雙工模式:無阻塞,大大提升了資源利用率。

和大家所熟知的 Nacos 對比,我們在金融級和分佈式(存儲量級)上具有很大優勢,易用性和雲原生方面,目前還在追趕。

歡迎加入我們

一個人可以走得很快,但一羣人可以走的更遠。

——題記

SOFARegistry 是一個開源項目,也是開源社區 SOFA 重要的一環,我們希望用社區的力量推動 SOFARegistry 的前進,而不是隻有螞蟻的工程師去開發。我們在今年也啓動了兩個項目,用於支持更多的開發者參與進來:

Trun-Key Project (開箱即用計劃):

https://github.com/sofastack/sofa-registry/projects/5

Deep-Dive Project(深入淺出計劃):

https://github.com/sofastack/sofa-registry/projects/4

計劃目前還處在初期階段,歡迎大家加入進來,可以幫助我們解決一個 issue,或是寫一篇文檔,都可以更好地幫助社區,幫助自己去成長。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/y371tkAXXEOCdCMOBl2tBA