阿里巴巴微服務註冊中心ConfigServer

1Eureka1.0 架構存在的問題

Eureka 作爲 Netflix 公司力推和 SpringCloud 微服務標配的註冊中心開源解決方案,其 Eureka 2.0 (Discontinued) 的消息在社區引起了不小的騷動;其實早在 2015 年社區就已經放出了 2.0 架構的升級設想,但是 3 年的時間過去,等到的確是 Discontinued 的消息,雖然 2.0 的代碼在 github 的主頁上也已經放出,但是告誡用戶要自行承擔當中的使用風險。我想不會有人真的把 2.0 直接投入到生產中使用。

對於爲什麼要做 Eureka2.0,其官方的 wiki 中的 Why Eureka 2.0 和 Eureka 2.0 Improvements 做了說明,Eureka1.0 的架構主要存在如下的不足:

  • 閱端拿到的是服務的全量的地址:這個對於客戶端的內存是一個比較大的消耗,特別在多數據中心部署的情況下,某個數據中心的訂閱端往往只需要同數據中心的服務提供端即可。
  • pull 模式:客戶端採用週期性向服務端主動 pull 服務數據的模式(也就是客戶端輪訓的方式),這個方式存在實時性不足以及無謂的拉取性能消耗的問題。
  • 一致性協議:Eureka 集羣的多副本的一致性協議採用類似“異步多寫”的 AP 協議,每一個 server 都會把本地接收到的寫請求(register/heartbeat/unregister/update)發送給組成集羣的其他所有的機器(Eureka 稱之爲 peer),特別是 hearbeat 報文是週期性持續不斷的在 client->server->all peers 之間傳送;這樣的一致性算法,導致瞭如下問題
  • 每一臺 Server 都需要存儲全量的服務數據,Server 的內存明顯會成爲瓶頸。
  • 當訂閱者卻來越多的時候,需要擴容 Eureka 集羣來提高讀的能力,但是擴容的同時會導致每臺 server 需要承擔更多的寫請求,擴容的效果不明顯。
  • 組成 Eureka 集羣的所有 server 都需要採用相同的物理配置,並且只能通過不斷的提高配置來容納更多的服務數據

Eureka2.0 主要就是爲了解決上述問題而提出的,主要包含了如下的改進和增強:

  • 數據推送從 pull 走向 push 模式,並且實現更小粒度的服務地址按需訂閱的功能。
  • 讀寫分離:寫集羣相對穩定,無需經常擴容;讀集羣可以按需擴容以提高數據推送能力。
  • 新增審計日誌的功能和功能更豐富的 Dashboard。

Eureka1.0 版本存在的問題以及 Eureka2.0 架構設想和阿里巴巴內部的同類產品 ConfigServer 所經歷的階段非常相似(甚至 Eureka2.0 如果真的落地後存在的問題,阿里巴巴早已經發現並且已經解決),下面我帶着你來回顧一下我們所經歷過的。

2阿里巴巴服務註冊中心 ConfigServer 技術發現路線

阿里巴巴早在 2008 就開始了服務化的進程,在那個時候就就已經自研出服務發現解決方案(內部產品名叫 ConfigServer)。

當 2012 年 9 月 1 號 Eureka 放出第一個 1.1.2 版本的時候,我們把 ConfigServer 和 Eureka 進行了深度的對比,希望能夠從 Eureka 找到一些借鑑來解決當時的 ConfigServer 發展過程中碰到的問題(後面會提到);然而事與願違,我們已經發現 Eureka1.x 架構存在比較嚴重的擴展性和實時性的問題(正如上面所描述的),這些問題 ConfigServer 當時的版本也大同小異的存在,我們在 2012 年底對 ConfigServer 的架構進行了升級來解決這些問題。

當 2015 年 Eureka 社區放出 2.0 架構升級的聲音的時候,我們同樣第一時間查看了 2.0 的目標架構設計,我們驚奇的發現 Eureka 的這個新的架構同 2012 年底 ConfigServer 的架構非常相似,當時一方面感慨“英雄所見略同”,另一方也有些失望,因爲 ConfigServer2012 年的架構早就無法滿足阿里巴巴內部的發展訴求了。

下面我從頭回顧一下,阿里巴巴的 ConfigServer 的技術發展過程中的幾個里程碑事件。

32008 年,無 ConfigServer 的時代

藉助用硬件負載設備 F5 提供的 vip 功能,服務提供方只提供 vip 和域名信息,調用方通過域名方式調用,所有請求和流量都走 F5 設備。

遇到的問題:

  • 負載不均衡:對於長連接場景,F5 不能提供較好的負載均衡能力。如服務提供方發佈的場景,最後一批發布的機器,基本上不能被分配到流量。需要在發佈完成後,PE 手工去斷開所有連接,重新觸發連接級別的負載均衡。
  • 流量瓶頸:所有的請求都走 F5 設備,共享資源,流量很容易會打滿網卡,會造成應用之間的相互影響。
  • 單點故障:F5 設備故障之後,所有遠程調用會被終止,導致大面積癱瘓。

42008 年,ConfigServer 單機版 V1.0

單機版定義和實現了服務發現的關鍵的模型設計(包括服務發佈,服務訂閱,健康檢查,數據變更主動推送,這個模型至今仍然適用),應用通過內嵌 SDK 的方式接入實現服務的發佈和訂閱;這個版本很重要的一個設計決策就是服務數據變更到底是 pull 還是 push 的模式,我們從最初就確定必須採用 push 的模式來保證數據變更時的推送實時性(Eureka1.x 的架構採用的是 pull 的模式)

當時,HSF 和 Notify 就是採用單機版的 ConfigServer 來完成服務的發現和 topic 的發現。單機版的 ConfigServer 和 HSF、Notify 配合,採用服務發現的技術,讓請求通過端到端的方式流動,避免產生流量瓶頸和單點故障。ConfigServer 可以動態的將服務地址推送到客戶端,服務調用者可以知道所有提供此服務的機器,每個請求都可以通過隨機或者輪詢的方式選擇服務端,做到請求級別的負載均衡。這個版本已經能很好的解決 F5 設備不能解決的三個問題。

但是單機版本的問題也非常明顯,不具備良好的容災性。

52009 年初,ConfigServer 單機版 V1.5

單機版的 ConfigServer 所面臨的問題就是當 ConfigServer 在發佈 / 升級的時候,如果應用剛好也在發佈,這個時候會導致訂閱客戶端拿不到服務地址的數據,影響服務的調用;所以當時我們在 SDK 中加入了本地的磁盤緩存的功能,應用在拿到服務端推送的數據的時候,會先寫入本地磁盤,然後再更新內存數據;當應用重啓的時候,優先從本地磁盤獲取服務數據;通過這樣的方式解耦了 ConfigServer 和應用發佈的互相依賴;這個方式沿用至今。(我很驚訝,Eureka1.x 的版本至今仍然沒有實現客戶端磁盤緩存的功能,難道 Eureka 集羣可以保持 100% 的 SLA 嗎?)

62009 年 7 月,ConfigServer 集羣版本 V2.0

ConfigServer 的集羣版本跟普通的應用有一些區別:普通的應用通過服務拆分後,已經屬於無狀態型,本身已經具備良好的可擴展性,單機變集羣只是代碼多部署幾臺;ConfigServer 是有狀態的,內存中的服務信息就是數據狀態,如果要支持集羣部署,這些數據要不做分片,要不做全量同步;由於分片的方案並沒有真正解決數據高可用的問題(分片方案還需要考慮對應的 failover 方案),同時複雜度較高;所以當時我們選擇了單機存儲全量服務數據全量的方案。爲了簡化數據同步的邏輯,服務端使用客戶端模式同步:服務端收到客戶端請求後,通過客戶端的方式將此請求轉發給集羣中的其他的 ConfigServer,做到同步的效果,每一臺 ConfigServer 都有全量的服務數據。

這個架構同 Eureka1.x 的架構驚人的相似,所以很明顯的 Eureka1.x 存在的問題我們也存在;當時的緩解的辦法是我們的 ConfigServer 集羣全部採用高配物理來部署。

72010 年底,ConfigServer 集羣版 V2.5

基於客戶端模式在集羣間同步服務數據的方案漸漸無以爲繼了,特別是每次應用在發佈的時候產生了大量的服務發佈和數據推送,服務器的網卡經常被打滿,同時 cmsgc 也非常頻繁;我們對數據同步的方案進行了升級,去除了基於客戶端的同步模式,採用了批量的基於長連接級別的數據同步 + 週期性的 renew 的方案來保證數據的一致性(這個同步方案當時還申請了國家專利);這個版本還對 cpu 和內存做了重點優化,包括同步任務的合併,推送任務的合併,推送數據的壓縮,優化數據結構等;

這個版本是 ConfigServer 歷史上一個比較穩定的里程碑版本。

但是隨着 2009 年天貓獨創的雙十一大促活動橫空出世,服務數量劇增,應用發佈時候 ConfigServer 集羣又開始了大面積的抖動,還是體現在內存和網卡的吃緊,甚至漸漸到了 fullgc 的邊緣;爲了提高數據推送能力,需要對集羣進行擴容,但是擴容的同時又會導致每臺服務器的寫能力下降,我們的架構到了“按下葫蘆浮起瓢”的瓶頸。

82012 年底,ConfigServer 集羣版 V3.0

在 2011 年雙十一之前我們完成了 V3 架構的落地,類似 Eureka2.0 所設計的讀寫分離的方案,我們把 ConfigServer 集羣拆分成 session 和 data 兩個集羣,客戶端分片的把服務數據註冊到 session 集羣中,session 集羣會把數據異步的寫到 data 集羣,data 集羣完成服務數據的聚合後,把壓縮好的服務數據推送到 session 層緩存下來,客戶端可以直接從 session 層訂閱到所需要的服務數據;這個分層架構中,session 是分片存儲部分的服務數據的(我們設計了 failover 方案),data 存儲的是全量服務數據(天生具備 failover 能力);

data 集羣相對比較穩定,不需要經常擴容;session 集羣可以根據數據推送的需求很方便的擴容(這個思路和 Eureka2.0 所描述的思路是一致的);session 的擴容不會給 data 集羣帶來壓力的增加。session 集羣我們採用低配的虛擬機即可滿足需求,data 由於存儲是全量的數據我們仍然採用了相對高配的物理機(但是同 V2.5 相比,對物理機的性能要求已經答覆下降)。

這個版本也是 ConfigServer 歷史上一個劃時代的穩定的大版本。

92014 年,ConfigServer 集羣版 V3.5

2013 年,阿里巴巴開始落地了異地多活方案,從一個 IDC 漸漸往多個 IDC 跨越,隨之而來的對流量的精細化管控要求越來越高(比如服務的同機房調用,服務流量的調撥以支持灰度能力等),基於這個背景 ConfigServer 引入了服務元數據的概念,支持對服務和 IP 進行元數據的打標來滿足各種各樣的服務分組訴求。

102017 年,ConfigServer 集羣版 V4.0

V3 版本可見的一個架構的問題就是 data 集羣是存儲全量的服務數據的,這個隨着服務數的與日俱增一定會走到升級物理機配置也無法解決問題的情況(我們當時已經在生產使用了 G1 的垃圾回收算法),所以我們繼續對架構進行升級,基於 V3 的架構進行升級其實並不複雜;session 層的設計保持不變,我們把 data 進行分片,每一個分片同樣按照集羣的方式部署以支持 failover 的能力;

目前 V4 的版本已經穩定運行了 2 年多,2017 年雙十一所管理的服務實例數已經幾近千萬的級別,服務訂閱數已經超過 5 千萬。

11Nacos

作爲同屬於 AP 類型的註冊中心,Eureka 和 ConfigServer 發展過程中所面臨的諸多問題有很大的相似性,但是阿里巴巴這些年業務的跨越式發展,每年翻番的服務規模,不斷的給 ConfigServer 的技術架構演進帶來更高的要求和挑戰,我們有更多的機會在生產環境發現和解決一個個問題的過程中,做架構的一代代升級。我們正在計劃通過開源的手段把我們這些年在生產環境上的實踐經驗通過 Nacos(http://nacos.io) 產品貢獻給社區,一方面能夠助力和滿足同行們在微服務落地過程當中對工業級註冊中心的訴求,另一方面也希望通過開源社區及開源生態的協同發展給 ConfigServer 帶來更多的可能性。

炎炎夏日,在 Eureka 2.0 (Discontinued) 即將結束的時候,在同樣的雲原生時代,Nacos 卻正在迎來新生,技術演進和變遷的趣味莫過於此。

Nacos 將努力繼承 Eureka 未竟的遺志,扛着 AP 系註冊中心的旗幟繼續前行,不同的是 Nacos 更關注 DNS-based Service Discovery 以及與 Kubernetes 體系的融會貫通。

我們看不透未來,卻仍將與同行們一起上下求索,砥礪前行。

最後附上 Nacos 的架構圖。

 

作者介紹

許真恩 (慕義),阿里巴巴高級技術專家

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章