降本提效!註冊中心在螞蟻集團的蛻變之路

文|林育智(花名:源三 )

螞蟻集團高級專家 專注微服務/服務發現相關領域

校對|李旭東

本文 8624 字 閱讀 18 分鐘

|引 言|

服務發現是構建分佈式系統的最重要的依賴之一, 在螞蟻集團承擔該職責的是註冊中心和 Antvip,其中註冊中心提供機房內的服務發現能力,Antvip 提供跨機房的服務發現能力。

本文討論的重點是註冊中心和多集羣部署形態(IDC 維度),集羣和集羣之間不涉及到數據同步。

PART. 1 背 景

回顧註冊中心在螞蟻集團的演進,大概起始於 2007/2008 年,至今演進超過 13 年。時至今日,無論是業務形態還是自身的能力都發生了巨大的變化。

簡單回顧一下注冊中心的歷代發展:

V1:引進淘寶的 configserver

img

V2:橫向擴展

img

從這個版本開始,螞蟻和阿里開始獨立的演進,最主要的差異點是在數據存儲的方向選擇上。螞蟻選擇了橫向擴展,數據分片存儲。阿里選擇了縱向擴展,加大 data 節點的內存規格。

這個選擇影響到若干年後的 SOFARegistry 和 Nacos 的存儲架構。

V3 / V4:LDC 支持和容災

img

V3 支持 LDC 單元化。

V4 增加了決策機制和運行時列表,解決了單機宕機時需要人工介入處理的問題,一定程度上提升高可用和減少運維成本。

V5:SOFARegistry

img

前四個版本是 confreg,17 年啓動 V5 項目 SOFARegistry,目標是:

1.代碼可維護性:confreg 代碼歷史包袱較重

  • 少量模塊使用 guice 做依賴管理,但大部分模塊是靜態類交互,不容易分離核心模塊和擴展模塊,不利於產品開源。

  • 客戶端與服務端的交互模型嵌套複雜,理解成本極高且對多語言不友好。

2.運維痛點:引入 Raft 解決 serverlist 的維護問題,整個集羣的運維包括 Raft,通過 operator 來簡化。

3.魯棒性:在一致性 hash 環增加多節點備份機制(默認 3 副本),2 副本宕機業務無感。

4.跨集羣服務發現:站內跨集羣服務發現額外需要 antvip 支撐,希望可以統一 2 套設施的能力,同時商業化場景也有跨機房數據同步的需求。

這些目標部分實現了,部分實現的還不夠好,例如運維痛點還殘留一部分,跨集羣服務發現在面對主站的大規模數據下穩定性挑戰很大。

V6:SOFARegistry 6.0

2020 年 11 月,SOFARegistry 總結和吸收內部/商業化打磨的經驗,同時爲了應對未來的挑戰,啓動了 6.0 版本大規模重構計劃。

歷時 10 個月,完成新版本的開發和升級工作,同時鋪開了應用級服務發現。

PART. 2 挑 戰

當下面臨的問題

集羣規模的挑戰

  • 數據增長:隨着業務的發展,業務的實例數在不斷增長,pub/sub 的數量也相應增長。以其中一個集羣爲例,2019 年的數據爲基準數據,在 2020 年 pub 接近千萬級。

下圖是該集羣歷年雙十一時的數據對比和切換應用級的優化效果。相比 2019 年雙十一,2021 年雙十一接口級的 pub 增長 200%,sub 增長 80%。

img

  • 故障爆炸半徑增長:集羣接入的實例越多,故障影響的業務和實例數也就越多,保障業務的穩定是最基礎也是優先級最高的要求。

  • 考驗橫向擴展能力:集羣達到一定的規模後,是否還具備繼續橫向擴展的能力,需要集羣具備良好的橫向擴展能力,從 10 擴到 100 和從 100 擴到 500 是不一樣的難度。

  • HA 能力:集羣實例數多了後,面臨的節點總體的硬件故障率也相應增高,各種機器故障集羣是否能快速恢復?有運維經驗的同學都知道,運維一個小集羣和運維一個大集羣面臨的困難簡直是指數級增長。

  • 推送性能:大多數服務發現的產品都選擇了數據的最終一致性,但是這個最終在不同集羣的規模下到底是多久?相關的產品其實都沒有給出明確的數據。

但是實際上,我們認爲這個指標是服務發現產品的核心指標。這個時長對調用有影響:新加的地址沒有流量;刪除的地址沒有及時摘除等。螞蟻集團的 PaaS 對註冊中心的推送時延是有 SLO 約束的:如果變更推送列表延時超過約定值,業務端的地址列表就是錯誤的。我們歷史上也曾發生過因推送不及時導致的故障。

業務實例規模增加的同時也帶來推送的性能壓力:發佈端 pub 下面的實例數增加;訂閱端業務實例數增加;一個簡單的估算,pub/sub 增長 2 倍,推送的數據量是 2*2,增長 4 倍,是一個乘積的關係。同時推送的性能也決定了同一時間可以支持的最大運維業務實例數,例如應急場景下,業務大規模重啓。如果這個是瓶頸,就會影響故障的恢復時間。

集羣規模可以認爲是最有挑戰性的,核心的架構決定了它的上限,確定後改造成本非常高。而且往往等到發現瓶頸的時候已經是兵臨城下了,我們要選擇能拉高產品技術天花板的架構。

運維的挑戰

SOFARegistryX 立項時的一個主要目標是具備比 confreg 更好的運維能力:引入 meta 角色,通過 Raft 選舉和存儲元信息,提供集羣的控制面能力。但是事實證明,我們還是低估了可運維的重要性,正如魯迅先生說:【程序員的工作只有兩件事情,一件是運維,另一件還是運維】。

三年前的目標放到今天已經嚴重滯後了。

  • 集羣數增長:螞蟻集團內部的業務是分站點部署的(簡單理解爲每個站點是一塊相對比較獨立的業務,需要不同級別的隔離),同時一個站點需要部署多套集羣:容災需要分機房部署;開發需要分多環境。部署站點的數目增長超出我們的想像。現在已經達到數百個集羣了,還在迅速增長中,增長速度參考最近幾年美聯儲的貨幣供應量增長速度。以前認爲有些運維工作可以苟且,人肉頂一下,集羣數增長後,苟且次數太多了,擠佔了開發/運維同學的精力,完全沒資源去規劃詩和遠方。

img

  • 業務打擾:業務的運維是全天候 7*24 的,容量自適應/自愈/MOSN 每月一版本把全站應用犁一遍等等。下圖是每分鐘運維的機器批數,可以看到,就算是週末和深夜,運維任務也是不斷的。

img

螞蟻集團的同學對註冊中心的運維公告應該是比較熟悉和痛恨的。因爲業務的敏感性,註冊中心之前一直是停機發布和運維,這個時候需要鎖定全站的發佈/重啓動作。爲了儘量少影響業務,註冊中心相關的同學只能獻祭一頭黑髮,在深夜低峯期做相關的操作。即使這樣,仍然沒辦法做到對業務零打擾。

雲原生時代 naming 的挑戰

img

雲原生的技術時代下,可以觀察到一些趨勢:

  • 微服務/FaaS 的推廣導致輕型應用增多:實例數增多,需要能支撐更大的業務規模

  • 應用實例的生命週期更短:FaaS 按需使用,autoscale 容量自適應等手段導致實例的漲潮退潮更頻繁,註冊中心的性能主要體現在實例變更的響應速度上

  • 多語言支持:在過去,螞蟻集團主要的開發體系是 Java,非 Java 語言對接基礎設施都是二等公民,隨着 AI 和創新性業務的需求,非 Java 體系的場景越來越多。如果按照每種語言一個 SDK,維護成本會是個噩夢,當然 sidecar(MOSN)是個解法,但是自身是否能支持低侵入性的接入方式,甚至 sdk-free 的能力?

  • 服務路由:在過去絕大部分的場景都可以認爲 endpoint 是平等的,註冊中心只提供通信的地址列表是可以滿足需求的。在 Mesh 的精確路由場景裏面,pilot 除了提供 eds(地址列表)也同時提供 rds(routing),註冊中心需豐富自身的能力。

  • K8s:K8s 當前已經成爲事實上的分佈式操作系統,K8s-service 如何和註冊中心打通?更進一步,是否能解決 K8s-service 跨 multi-cluster 的問題?

「總結」

綜上,除了腳踏實地,解決當下的問題,還需要仰望星空。具備解決雲原生趨勢下的 naming 挑戰的可能性,也是 V6 重構的主要目標。

PART. 3 SOFARegistry 6.0:面向效能

SOFARegistry 6.0 不只是一個註冊中心引擎,需要和周邊的設施配合,提升開發、運維、應急的效能,解決以下的問題。(紅色模塊是比較有挑戰性的領域)

img

SOFARegistry 6.0 相關的工作包括:

img

架構優化

架構的改造思路:在保留 V5 的存儲分片架構的同時,重點的目標是優化元信息 meta 一致性和確保推送正確的數據。

img

元信息 meta 一致性

V5 在 meta 角色中引入 Raft 的強一致性進行選舉 leader 和存放元信息,其中元信息包括節點列表和配置信息。數據的分片通過獲取 meta 的節點列表做一致性 hash,這裏面存在兩個問題:

  • Raft/operator 運維複雜

    (1)定製運維流程:需要支持 change peer 等編排。在螞蟻集團,特化的運維流程成本較高,同時也不利於輸出。

    (2)實現一個生產健壯的 operator 成本非常高,包括接入變更管控 operator 自身的變更三板斧等。

    (3)對於網絡/磁盤的可用性比較敏感。在輸出的場景,會面臨比較惡劣的硬件情況,排查成本較高。

  • 脆弱的強一致性

meta 信息的使用建立在滿足強一致性的情況下,如果出現網絡問題,例如有 session 網絡分區連不上 meta,錯誤的路由表會導致數據分裂。需要機制確保:即使 meta 信息不一致也能在短時間內維持數據的正確性,留有應急的緩衝時間。

推送正確的數據

當 data 節點大規模運維時,節點列表劇烈變化導致數據不斷遷移,推送出去的數據存在完整性/正確性的風險。V5 通過引 3 副本來避免這種情況,只要有一個副本可用,數據就是正確的,但是該限制對運維流程負擔很大,我們要確保每次操作少於兩個副本或者挑選出滿足約束的運維序列。

對於 V5 及之前的版本,運維操作是比較粗糙的,一刀切做停機發布,通過鎖 PaaS 禁止業務變更,等 data 節點穩定後,再打開推送能力來確保避免推送錯誤數據的風險。

此外,預期的運維工作可以這樣做,但是對於突發的多 data 節點宕機,這個風險仍然是存在的。

我們需要有機制確保:data 節點列表變化導致數據遷移時,容忍接受額外的輕微推送時延,確保推送數據正確。

「成果」

  • meta 存儲/選舉 組件插件化,站內去 Raft,使用 db 做 leader 選舉和存儲配置信息,降低運維成本。

  • 數據使用固定 slot 分片,meta 提供調度能力,slot 的調度信息通過 slotTable 保存,session/data 節點可容忍該信息的弱一致性,提升魯棒性。

  • 多副本調度減少 data 節點變動時數據遷移的開銷,當前線上的數據量 follower 升級 leader 大概 200ms (follower 持有絕大部分的數據),直接分配 leader 數據同步耗時 2s-5s。

  • 優化數據通信/複製鏈路,提升性能和擴展能力。

  • 大規模運維不需要深夜鎖 PaaS,減少對業務打擾和保住運維人員頭髮,提升幸福感。

數據鏈路和 slot 調度:

  • slot 分片參考 Redis Cluster 的做法,採用虛擬哈希槽分區,所有的 dataId 根據哈希函數映射到 0 ~ N 整數槽內。

  • meta 的 leader 節點,通過心跳感知存活的 data 節點列表,儘可能均勻的把 slot 的多副本分配給 data 節點,相關的映射關係保存在 slotTable,有變更後主動通知給 session/data。

  • session/data 同時通過心跳獲取最新的 slotTable,避免 meta 通知失效的風險。

  • slot 在 data 節點上有狀態機 Migrating -> Accept -> Moved。遷移時確保 slot 的數據是最新的才進入 Accept 狀態,纔可以用於推送,確保推送數據的完整性。

img

data 節點變動的數據遷移:

img

對一個接入 10w+ client 的集羣進行推送能力壓測,分鐘級 12M 的推送量,推送延遲 p999 可以保持在 8s 以下。session cpu20%,data cpu10%,物理資源水位較低,還有較大的推送 buffer。

img

同時我們也在線上驗證橫向擴展能力,集羣嘗試最大擴容到 session370,data60,meta*3 ;meta 因爲要處理所有的節點心跳,CPU 達到 50%,需要 8C 垂直擴容或者進一步優化心跳開銷。按照一個 data 節點的安全水位支撐 200w pub,一個 pub 大概 1.5K 開銷,考慮容忍 data 節點宕機 1/3 仍然有服務能力,需要保留 pub 上漲的 buffer,該集羣可支撐 1.2 億的 pub,如果配置雙副本則可支撐 6kw 的 pub。

應用級服務發現

註冊中心對 pub 的格式保留很強的靈活性,部分 RPC 框架實現 RPC 服務發現時,採用一個接口一個 pub 的映射方式,SOFA/HSF/Dubbo2 都是採用這種模式,這種模型比較自然,但是會導致 pub/sub 和推送量膨脹非常厲害。

Dubbo3 提出了應用級服務發現和相關原理【1】。在實現上,SOFARegistry 6.0 參考了 Dubbo3,採用在 session 端集成服務的元數據中心模塊的方案,同時在兼容性上做了一些適配。

「應用級服務 pub 數據拆分」

img

「兼容性」

應用級服務發現的一個難點是如何低成本的兼容接口級/應用級,雖然最後大部分的應用都能升級到應用級,升級過程中會面臨以下問題:

  • 應用數多,同時各個應用升級到應用級的時間點差距比較大

  • 部分應用無法升級,例如一些遠古應用

我們採用以應用級服務爲主,同時兼容接口級的解決方案:

img

在升級時同時存在新舊版本的兩個 SOFARegistry,不同版本的 SOFARegistry 對應到不同的域名。升級後的應用端(圖中的 MOSN)採用雙訂閱雙發佈的方式逐步灰度切換,確保切換過程中,沒有升級接入 MOSN 或者沒有打開開關的應用不受影響。

在完成絕大多數應用的應用級遷移後,升級後的應用都已經到了 SOFARegistry 6.0 版本的註冊中心上,但仍然存在少量應用因爲沒有接入 MOSN,這些餘留的 old app 也通過域名切換到 SOFARegistry 6.0,繼續以接口級訂閱發佈和註冊中心交互。爲了確保已升級的和沒升級的應用能夠互相訂閱,做了一些支持:

  • 提供應用級 Publisher 轉接到口級 Publisher 的能力:接口級訂閱端是無法直接訂閱應用級發佈數據的,針對接口級訂閱按需從 AppPublisher 轉換出 InterfacePublisher,沒有接入 MOSN 的應用可以順利的訂閱到這部分數據,因爲只有少量應用沒有接入 MOSN,需要轉化的應用級 Publisher 很少。

  • 應用級訂閱端在訂閱的時候額外發起一個接口級的訂閱,用於訂閱沒有接入升級的應用發佈數據。由於這部分應用非常少,實際絕大多數的服務級訂閱都不會有推送任務,因此對推送不會造成壓力。

「效果」

img

上圖是一個集羣切換應用級後的效果,其中切換後剩餘部分接口級 pub 是爲了兼容轉換出來的數據,接口級 sub 沒減少也是爲了兼容接口級發佈。如果不考慮兼容性,pub 數據減少高達 97%。極大的減輕了數據規模的對集羣的壓力。

SOFARegistryChaos:自動化測試

註冊中心的最終一致性的模型一直是個測試難題:

  • 最終是多久?

  • 達到最終前有沒有推送錯誤的數據

  • 達到最終前有沒有推送少數據

  • 集羣發生故障/數據遷移時對數據的正確性和時延的影響

  • client 端頻繁按照各種順序調用 API 的影響

  • client 端頻繁連接斷連的影響

針對該系列問題,我們開發了 SOFARegistryChaos,特別針對最終一致性提供完備的測試能力,除此還提供功能/性能/大規模壓測/混沌測試等能力。同時,通過插件化的機制,也支持接入測試其他服務發現產品的能力,基於 K8s 的部署能力,能讓我們快速的部署測試組件。

具備以上的能力後,不單可以測試自身的產品能力,例如還可以快速的測試 zookeeper 在服務發現方面的相關性能來做產品比較。

img

測試觀測性

提供的關鍵數據的觀測能力,通過 metrics 透出,對接 Prometheus 即可提供可視化能力:

  • 推送時延

  • 設定時間內的最終一致性檢測

  • 發生故障注入的時間點

  • 最終一致期間推送數據的完整性 該能力的測試是一個比較有意思的創新點,通過固化一部分的 client 和對應的 pub,校驗每次其他各種變更導致的推送數據,這部分數據都必須是要完整和正確的。

  • 推送次數

  • 推送數據體積

img

失敗 case 的排查

測試場景中,client 操作時序和故障注入都是隨機編排的,我們在 SOFARegistryChaos master 端記錄和收集了所有的操作命令時序。當 case 失敗時,可通過失敗的數據明細和各個 client 的 API 調用情況來快速定位問題。

例如下圖的失敗 case 顯示在某個 Node 上的訂閱者對某個 dataId 的訂閱數據沒通過校驗,預期是應該要推空, 但是推送了一條數據下來。同時顯示了該 dataId 所有相關的 publisher 在測試期間的相關操作軌跡。

img

黑盒探測

大家是否經歷過類似的 case:

  • 突然被業務告知系統出現問題,一臉懵的我:系統沒異常啊

  • 發現系統出現故障時,實際已經對業務造成了嚴重影響

註冊中心因爲本身的特性,對業務的影響往往是滯後的,例如 2K 個 IP 只推送了 1K 個,這種錯誤不會導致業務馬上感知到異常。但是實際本身已經出問題了。對於註冊中心,更需要有提前發現治末病的能力。

這裏我們引入黑盒探測的方式:模擬廣義上的用戶行爲,探測鏈路是否正常。

SOFARegistryChaos 實際上就可以作爲一個註冊中心的用戶,並且是加強版的,提供端到端的告警能力。

我們把 SOFARegistryChaos 部署到線上,開啓小流量作爲一個監控項。當註冊中心異常但還沒對業務造成可感知的影響時,我們有機會及時介入,減少風險事件升級成大故障的風險。

磨刀不誤砍柴工

通過 SOFARegistryChaos,核心能力的驗證效率極大提升,質量得到保障的同時,開發同學寫代碼也輕鬆了許多。從 7 月份到 10 月中的 3 個半月時間裏,我們迭代併發布了 5 個版本,接近 3 周 1 個版本。這個開發效率在以前是不敢想象的,同時也獲得完善的端到端告警能力。

運維自動化

nightly build

雖然我們集羣數目非常多,但是因爲是區分了多環境,部分環境對於穩定性的要求相對生產流量要求稍微低一些,例如灰度以下的環境。這些環境的集羣是否可以在新版本保證質量的情況下,快速低成本的 apply 。結合 SOFARegistryChaos,我們和質量/SRE 的同學正在建設 nightly build 設施。

SOFARegistryChaos 作爲變更門禁,新版本自動化的部署,接受 SOFARegistryChaos 的測試通過後,自動化部署到灰度以下的集羣,僅在生產發佈時候人工介入。

img

通過 nightly build,極大的減輕非生產環境的發佈成本,同時新版本能儘早接受業務流量的檢驗。

故障演練

雖然我們做了大量的質量相關的工作,但是在線上面對各種故障時究竟表現如何?是騾子還是馬,還是要拉出來溜一溜。

我們和 SRE 的同學在線上會定期做故障容災演練,包括但不限於網絡故障;大規模機器宕機等。另外演練不能是一錘子買賣的事情,沒有保鮮的容災能力其實等於 0。在仿真/灰度集羣,進行容災常態化,演練-迭代循環。

img

定位診斷

故障容災演練常態化後,如何快速的定位到故障源成了擺在桌子上的一個問題,否則每次演練都雞飛狗跳的,效率太低了。

SOFARegistry 各個節點做了大量的可觀測性的改進,提供豐富的可觀測能力,SRE 的診斷系統通過相關數據做實時診斷,例如這個 case 裏就是一個 session 節點故障導致 SLO 破線。有了定位能力後,自愈系統也可以發揮作用,例如某個 session 節點被診斷出網絡故障,自愈系統可以觸發故障節點的自動化替換。

img

目前,我們的容災演練應急絕大部分 case 已經不需要人肉介入,也只有這樣低成本的演練才能常態化。

「收益」

通過不斷的演練暴露問題和快速迭代修復,SOFARegistry 的穩定性逐步提升。

「總結」

SOFARegistry 6.0 除了自身的優化,在測試/運維/應急方面做了大量的工作,目標是提升研發/質量/運維人員的效能,讓相關同學擺脫低效的人肉工作,提升幸福感。

PART. 4 開源:一個人可以走得很快,但一羣人可以走的更遠

SOFARegistry 是一個開源項目,也是開源社區 SOFAStack 重要的一環,我們希望用社區的力量推動 SOFARegistry 的前進,而不是隻有螞蟻集團的工程師去開發。

在過去一年,SOFARegistry 因爲重心在 6.0 重構上,社區幾乎處於停滯狀態,這個是我們做得不夠好的地方。

我們制定了未來半年的社區計劃,在 12 月份會基於內部版本開源 6.0,開源的代碼包含內部版本的所有核心能力,唯一區別是內部版本多了對 confreg-client 的兼容性支持。

img

另外從 6.1 後,我們希望後繼的方案設計/討論也是基於社區來開展,整個研發進程更透明和開放。

PART. 5 我們仍在路上

2021 年是 SOFARegistry 審視過去,全面夯實基礎,提升效能的一年。

當然,我們當前還仍然處在初級階段,前面還有很長的路要走。例如今年雙十一的規模面臨一系列非常棘手的問題:

  • 一個集羣內單應用實例數過多(熱點應用單集羣高達 7K 個實例)導致業務端收到地址推送時 CPU/memory 開銷過大。

  • 全地址列表推送,導致的連接數過多等。

還有其他的挑戰:

  • 增量推送,減少推送數據量和 client 端的資源開銷

  • 統一服務發現,支持跨集羣

  • 適應雲原生下的新趨勢

  • 社區的運營

  • 產品易用性

「參 考」

【1】Dubbo3 提出了應用級服務發現和相關原理:

https://dubbo.apache.org/zh/blog/2021/06/02/dubbo3-%E5%BA%94%E7%94%A8%E7%BA%A7%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0/

關於我們:

螞蟻應用服務團隊是服務於整個螞蟻集團的核心技術團隊,打造了世界領先的金融級分佈式架構的基礎設施平臺,是 Service Mesh 等雲原生領域的領先者,開發運維着全球最大的 Service Mesh 集羣,螞蟻集團的消息中間件每天支撐上萬億的消息流轉。

歡迎對 Service Mesh/微服務/服務發現 等領域感興趣的同學加入我們。

聯繫郵箱: [email protected]

本週推薦閱讀

穩定性大幅度提升:SOFARegistry v6 新特性介紹

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

Prometheus on CeresDB 演進之路)

如何在生產環境排查 Rust 內存佔用過高問題

img

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