服務發現框架 - Eureka 與阿里configcenter比較


本文簡單描述了 Eureka1.0 存在的架構問題,Eureka2.0 設想的架構。詳細回顧了阿里巴巴的服務注冊中心 ConfigServer 產品從 2008 年建設元年至今經歷的關鍵架構演進。通過這個文章你會對基於 AP 模式的注冊中心在技術發展過程中將會碰到的問題有所感知。

 

1. Eureka1.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 的技術發展過程中的幾個里程碑事件。

 

3. 2008 年,無 ConfigServer 的時代

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

遇到的問題:

  • 負載不均衡:對於長連接場景,F5 不能提供較好的負載均衡能力。如服務提供方發布的場景,最后一批發布的機器,基本上不能被分配到流量。需要在發布完成后,PE 手工去斷開所有連接,重新觸發連接級別的負載均衡。

  • 流量瓶頸:所有的請求都走 F5 設備,共享資源,流量很容易會打滿網卡,會造成應用之間的相互影響。

  • 單點故障:F5 設備故障之后,所有遠程調用會被終止,導致大面積癱瘓。

 

4. 2008 年,ConfigServer 單機版 V1.0

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

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

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

 

5.2009 年初,ConfigServer 單機版 V1.5

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

6.2009 年 7 月,ConfigServer 集群版本 V2.0

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

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

 

7. 2010 年底,ConfigServer 集群版 V2.5

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

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

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

 

8. 2012 年底,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 歷史上一個划時代的穩定的大版本。

 

9. 2014 年,ConfigServer 集群版 V3.5

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

 

10. 2017 年,ConfigServer 集群版 V4.0

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

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

 

11. Nacos

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

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

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

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

最后附上 Nacos 的架構圖。

 

作者介紹

轉載:https://mp.weixin.qq.com/s?__biz=MjM5MDE0Mjc4MA==&mid=2651008155&idx=1&sn=4846cddb6c9627ee0ec2f3c699c0b06c&chksm=bdbed4c88ac95dde2cf0f62286ad8936122f0cea8a718acb8c288e0b1977cdfcaacd0695d85a&mpshare=1&scene=23&srcid=0713yHQLMGZDbSZokxXYE0tz#rd 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM