螞蟻金服 Service Mesh 大規模落地系列 - 消息篇

1f149b18-be80-4afb-ac60-03e054dc6e7b.jpeg

《螞蟻金服 Service Mesh 大規模落地系列》將會從核心、RPC、消息、無線網關、控制面、安全、運維、測試等模塊對 Service Mesh 雙十一大規模落地實踐進行詳細解析,文末包含往期系列文章。

引言

Service Mesh 作爲螞蟻金服向下一代雲原生架構演進的核心基礎設施,在2019年得到了大規模的應用與落地,截止目前,螞蟻金服的 Service Mesh 數據平面 MOSN 已接入應用數百個,接入容器數量達數十萬,一舉成爲全世界最大的 Service Mesh 集羣。同時,在剛剛結束的雙十一大促中,Service Mesh 的表現也十分亮眼,RPC 峯值 QPS 達到了幾千萬,消息峯值 TPS 達到了幾百萬,且引入 Service Mesh 後的平均 RT 增長幅度控制在 0.2 ms 以內。

本文作爲整個 Service Mesh 系列文章的消息篇,作者:劉翔(花名:無勤),螞蟻金服消息 Mesh 負責人, 消息中間件核心研發成員,專注於高吞吐、低延遲的消息中間件研發,以及雲原生時代下一代消息系統的架構設計與研發。本文將從以下幾個方面對消息 Mesh 進行解讀:

  • 對消息 Mesh 進行介紹,解答消息 Mesh 在整個 Service Mesh 中的地位是什麼,它又能爲業務帶來哪些價值;

  • 結合螞蟻金服消息中間件團隊 Mesh 化的實踐與思考,闡述如何在消息領域進行 Mesh 化改造;

  • 消息 Mesh 在螞蟻金服內部大規模落地過程中遇到的問題與挑戰,以及對應的解決方案;

  • 消息流量精細化調度上的思考與在 Mesh 上的實現與落地;

消息 Mesh 簡介

Service Mesh 作爲雲原生場景下微服務架構的基礎設施(輕量級的網絡代理),正受到越來越多的關注。Service Mesh 不僅負責在微服務架構的複雜拓撲中可靠地傳遞請求,也將限流、熔斷、監控、鏈路追蹤、服務發現、負載均衡、異常處理等與業務邏輯無關的流量控制或服務治理行爲下沉,讓應用程序能更好地關注自身業務邏輯。

微服務架構中的通信模式實際上是多種多樣的,既包含同步的請求調用,也包含異步的消息/事件驅動,然而流行的 Service Mesh 實現(Istio,Linkerd,Consul Connect等),都仍侷限在對微服務中同步請求調用的關注,卻無法管理和追蹤異步消息流量。而消息 Mesh 則是對這一塊的重要補充,通過將消息 Mesh 有機地融合到 Service Mesh 中,可以幫助 Service Mesh 實現對所有微服務流量的管控和追蹤,從而進一步完善其架構目標。

消息 Mesh 的價值

在傳統的消息中間件領域,我們更關注的是消息服務端的性能、服務可用性、數據可靠性等核心指標,而與業務應用密切相關的一些能力,包括消息的流量控制(限流、熔斷、灰度、着色、分組等),消息的服務治理(消息量級與消息應用拓撲等),消息鏈路的追蹤(消息軌跡)卻往往不盡如人意。

這不僅是因爲傳統模式下上述能力的提供和優化都涉及客戶端的改造與大規模升級,整個過程常常比較漫長,難以快速根據有效反饋不斷優化,更重要的是缺乏一個統一的架構指導思想,混亂無序地向客戶端疊加相關功能只會讓消息客戶端變得越來越臃腫和難以維護,也變向增加了業務系統的接入、調試和排查問題的成本。而消息 Mesh 作爲 Service Mesh 的補充,能顯著帶來如下價值和收益:

  • 快速升級 - 通過將與業務邏輯無關的一些核心關鍵能力下沉到 Sidecar 中,使這些能力的單獨快速迭代與升級成爲可能;

  • 流量控制 - 可以向 Sidecar 中集成各種流量控制策略,例如可根據消息類型、消息數量、消息大小等多種參數來控制消息的發送和消費速率;

  • 流量調度 - 通過打通 Sidecar 節點之間的通信鏈路,可以利用 Sidecar 的流量轉發來實現任意精度的消息流量調度,幫助基於事件驅動的微服務應用進行多版本流量管理、流量着色、分組路由、細粒度的流量灰度與A/B策略等;

  • 消息驗證 - 消息驗證在基於事件驅動的微服務架構中正變得越來越重要,通過將這部分能力下沉到 Sidecar,不僅可以讓業務系統無縫集成消息驗證能力,也可以讓 Sidecar 通過 Schema 理解消息內容,並進一步具備惡意內容識別等安全管控能力;

  • 可觀測性 - 由於所有的消息流量都必須通過 Sidecar,因此可以爲 Sidecar 上的消息流量按需增加 Trace 日誌,Metrics 採集,消息軌跡數據採集等能力,並藉此進一步豐富消息服務的治理能力;

消息 Mesh 化改造

在螞蟻金服內部,Msgbroker 基於推模型提供高可靠、高實時、事務消息、header 訂閱等特性,幫助核心鏈路進行異步解耦,提升業務的可擴展能力,並先後伴隨螞蟻金服衆多核心繫統一起經歷了分佈式改造、單元化改造與彈性改造,目前主要承載螞蟻內部交易、賬務、會員、消費記錄等核心在線業務的異步消息流量。

由於 Service Mesh 的推進目標也是優先覆蓋交易支付等核心鏈路,爲在線業務賦能,因此我們優先選擇對 Msgbroker 系統進行 Mesh 化改造。下面將以 Msgbroker 爲例,重點剖析 Mesh 化後在整體架構和核心交互流程上的變化,爲消息領域的 Mesh 化改造提供參考。

整體架構

509843d1-97f0-4fdc-9061-5375d4563c88.png

消息 Mesh 化後的整體架構如上圖所示,與原有的消息架構相比,主要的變化有:

  • 客戶端不再與服務端直連,而是通過 Sidecar 進行請求的中轉,對客戶端而言,Sidecar 實際上是它唯一能感知到的消息服務端,對服務端而言,Sidecar 則扮演着客戶端的角色;

  • 所有 Sidecar 都會與控制平面交互,接收服務端地址列表、流量管控和調度配置、運行時動態配置等的下發,從而使數據平面具備限流、熔斷、異常重試、服務發現、負載均衡、精細化流量調度等能力;

核心交互流程

當 Sidecar 代理了消息客戶端的所有請求後,一旦 Sidecar 完成消息服務的發現與服務端/客戶端路由數據的緩存,無論是客戶端的發消息請求還是服務端的推消息請求,都能由 Sidecar 進行正確的代理轉發,而這一切的關鍵,則是 Sidecar 與消息客戶端協同完成一系列的初始化操作。

消息 Mesh 化後具體的初始化流程如下所示,與原有的初始化流程相對比,主要有如下不同:

  • 在經過 Mesh 化改造後,消息客戶端不再直接向 SOFARegistry 訂閱消息服務端的地址,而是將所有消息元數據(包含業務應用聲明的消息 Topic、發送/訂閱組 GroupId 等關鍵信息)通過 HTTP 請求上報給 MOSN,由 MOSN 進行元數據的持久化(用於 MOSN 異常 Crash 後的恢復)以及消息服務端地址的訂閱和處理;

  • 當客戶端收到 MOSN 對於註冊請求的響應時,會主動與 MOSN 建立連接,並將與該連接相關的 Group 集合信息通過控制指令發送給 MOSN,由於客戶端與 MOSN 可能存在多個連接,且不同連接上的 Group 集合可以不同,而 MOSN 與同一個消息服務端只維持一個連接,因此控制指令無法向消息數據一樣直接進行轉發,而是需要彙總計算所有 GroupId 集合後再統一廣播給消息服務端集羣。由於上述計算邏輯十分複雜,需要包含過濾和聚合,且存在動態和併發行爲,一旦因計算錯誤則會嚴重影響到消息投遞的正確性,因此當前 MOSN 繞過了該指令的代理,只利用客戶端的控制指令進行相關數據的校驗,以及更新客戶端連接的映射信息(用於 MOSN 的客戶端連接選擇),而是選擇依賴消息客戶端的改造引入上述 HTTP 註冊請求來構造全量控制指令;


MOSN:https://github.com/sofastack/sofa-mosn

c3f73233-417b-4119-b06e-a72cbaed2a6f.png

消息 Mesh 的挑戰

消息中間件最關鍵的挑戰,在於如何在洪峯流量下依然保障消息服務的高可靠與高實時。而在消息 Mesh 化的大規模實施過程中,還需要考慮數十萬的容器節點對數據面整體穩定性和控制面性能帶來的巨大挑戰,這些都依賴於完善的 Sidecar 運維體系,包括 Sidecar 的資源分配策略,以及 Sidecar 獨立變更升級的策略。

資源管理

當 Service Mesh 的實體 MOSN 作爲 Sidecar 與業務容器部署在一起時,就不再像消息服務端一樣只需要關心自身的資源消耗,而是必須精細化其 CPU、內存等資源的分配,才能達到與應用最優的協同合作方式。在 Sidecar 的精細化資源管理上,先後經歷了獨立分配、通過超賣與業務容器共享、細粒度的 CPU 資源分配策略和內存 OOM 策略調整等多個階段,最終基於 Service Mesh 將原有的與業務無關的邏輯下沉到 Sidecar,其佔用的資源實際是原來業務容器會使用的資源這一假設,在零新增成本的情況下平穩支撐了數十萬規模級別的 Sidecar 容器分配。關於資源管理更詳細的內容可以期待後續 Service Mesh 系列文章中的運維篇,本文就不再贅述。

平滑升級

爲了達到 Sidecar 這一類基礎設施的變更升級對業務完全無感知的目的,就需要使 MOSN 具備平滑升級的能力。在平滑升級過程中,新的 MOSN 首先會被注入,並通過共享卷的 UnixSocket 去檢查是否存在老的 MOSN,若存在,則利用內核 Socket 的遷移實現老 MOSN 的連接全部遷移給新 MOSN,如下圖所示,最終再讓老 MOSN 優雅退出,從而實現 MOSN 在整個升級和發佈過程中對業務無任何打擾,關於 MOSN 本身平滑升級更多的內容,可以參考 Service Mesh 系列文章中的核心篇

843e2c37-7955-4dcd-8cfd-7c03581647ad.png

上述平滑升級方案,其實隱含了一個非常重要的前提,單條連接上的請求必須是單向的。從下圖可知,對於 RPC 場景,其單條連接的角色是固定的,只能是服務端連接或客戶端連接,且對一次請求的代理過程也是固定的,總是從服務端連接上收到一個請求,再從客戶端連接將請求轉發出去,因此 RPC 可以直接使用上述平滑升級方案。

c333e1bd-7052-48d3-9131-af434d1c5d10.png

然而,在消息場景特別是 Msgbroker 場景下,如下圖所示,MOSN 上的連接請求實際上是雙向的,不僅客戶端會使用該連接進行消息的發送,服務端也會利用該連接將消息主動推送給 MOSN,這就會給上述連接遷移帶來新的問題和挑戰:

  • 在連接遷移的過程中,如果消息客戶端已處理完經過 MOSN 轉發的服務端投遞消息請求,但是還未回覆響應,此時若把連接遷移到新的 MOSN,則新的 MOSN 將收到上述響應,但由於新 MOSN 缺失上下文,無法將該響應返回給正確的消息服務端

  • 在連接遷移完成,但老 MOSN 還未優雅退出期間,由於兩個 MOSN 與消息服務端都存在連接,兩者都會收到服務端發送的投遞消息請求,但因兩個 MOSN 與服務端連接的狀態各自獨立,可能會使客戶端收到的請求ID衝突

0b0d2f97-a52c-4fad-8893-96cd2cca66da.png

解決上述問題的思路其實很簡單,即爲在平滑升級的過程中,禁止服務端向老 MOSN 發送投遞消息請求,保證即使在消息場景整個平滑升級過程中的所有連接仍然是單工通信的。具體對平滑升級流程的改動如下:

  • 老 MOSN 平滑升級指令後,會立即向所有的消息服務端發送禁止再接收消息的控制指令;

  • 新 MOSN 感知老 MOSN 完成前置操作,開始進行原有的平滑升級流程,進行初始化和存量連接遷移;

  • 新 MOSN 完成存量連接遷移後,向所有的消息服務端發送接收消息的控制指令,開始正常的消息訂閱;

消息 Mesh 流量調度

消息 Mesh 的流量調度如下圖所示。

首先,控制平面會將與流量調度相關的規則下發至 MOSN,規則主要包含該應用下所有容器節點的 IP 地址與流量權重,這是能夠進行精細化流量調度的前提。

其次,當 MOSN 收到消息投遞請求時,會判斷請求的來源,若請求來源於其他 MOSN 節點,則會直接將該請求轉發給客戶端,避免消息投遞請求的循環轉發,而若請求來源於消息服務端,則 MOSN 會根據自身的流量權重來決定下一步的路由,若自身的流量權重是100%,會同樣將該請求轉發給客戶端,但若自身權重小於100%,則會按照配置的權重將剩餘請求均勻轉發給其他流量權重爲100%的 MOSN 節點。

最後,與 RPC 的點對點通信方式不同,無論是消息發送端還是訂閱端都只與消息服務端通信,這意味着即使進行了消息 Mesh 化改造後,MOSN 也只與消息服務端通信,同一個應用的 MOSN 節點之間是不存在消息連接的,爲了實現 MOSN 之間的消息流量轉發,則需要內置實現一個與業務應用進程同生命週期的消息轉發服務,由同應用內的所有其他 MOSN 節點訂閱並在需要轉發時調用。

a4590545-1c4f-44be-bffa-241ed69f98bf.png

總結

消息 Mesh 經過螞蟻消息中間件團隊大半年的打磨和沉澱,已經邁出了堅實的一大步:在開源社區遲遲未在消息 Mesh 上取得實質性進展時,我們已經爲螞蟻內部主流消息中間件打通了數據平面。

同時也有充滿想象力的一小步:依賴消息的精細化流量調度,預期可以發揮更大的業務價值,包括基於事件驅動的 Serverless 化應用多版本流量管理、流量着色、分組路由、細粒度的流量灰度與A/B策略等,等待着去開發與挖掘,

這些都在雙十一大促中取得了不俗的成績。未來,我們將會持續加大對消息 Mesh的投入,爲消息 Mesh 支持更多的消息協議,賦予更多開箱即用的的消息流量管控和治理能力,並進一步結合 Knative 探索消息精細化流量調度在 Serverless 下的應用場景。最後,也歡迎志同道合的夥伴加入我們,一起參與金融級分佈式消息系統、雲原生時代的下一代消息系統的架構設計和研發。

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