天天看點

螞蟻科技 Service Mesh 落地實踐與挑戰

本文整理自 GIAC(GLOBAL INTERNET ARCHITECTURE CONFERENCE)全球網際網路架構大會,螞蟻科技平台資料技術事業群技術專家石建偉(花名:卓與)的分享。分享基于 Service Mesh 的理念,結合螞蟻科技内部實際場景,将中間件、資料層、安全層等能力從應用中剝離出來後下沉至獨立的 Sidecar SOFAMosn 中,結合 Kubernetes 運維體系,提供應用無感覺的情況下更新基礎設施層能力的案例。

螞蟻科技 Service Mesh 落地實踐與挑戰

本次分享将從以如下次序展開進行:

螞蟻科技 Service Mesh 落地實踐與挑戰

| 螞蟻科技目前的服務化現狀

在看螞蟻科技的服務化架構之前我們先從一個簡單的服務化調用示例說起,下圖是 SOFARPC 基本原理:

螞蟻科技 Service Mesh 落地實踐與挑戰

圖1. SOFARPC 基本原理

我們從上圖可以看出,建構一個服務化架構需要有服務注冊中心,有服務定義,調用方和服務提供方使用相同的服務定義來互相通訊。通過服務注冊中心,調用方可以直接訂閱到服務提供方的位址,采用點對點的方式直接發起請求。用戶端内可實作服務發現、路由尋址、負載均衡、限流熔斷等能力來增強服務通訊能力。通過我們開源的 SOFARPC、SOFARegistry、SOFABoot,使用者已經可以直接建構起微服務體系,助力業務發展。

螞蟻科技發展至今,雙 11 系統需要應對的交易洪峰逐年遞增:

螞蟻科技 Service Mesh 落地實踐與挑戰

圖2. 曆年雙 11 交易額與峰值資料

每秒 26.5 萬筆交易是 2017 年雙 11 的峰值資料,這個資料背後有非常複雜的架構支援,LDC 單元化架構是螞蟻科技沉澱多年的核心架構,依靠這個架構實作每年峰值交易量飛速增長下系統依然能平滑渡過。我們來簡要看下 LDC 架構:

螞蟻科技 Service Mesh 落地實踐與挑戰

圖3. LDC 架構示例

上圖摘自 金融級分布式架構 中的 素描單元化 一文,這裡不詳細展開。LDC 的單元化架構給應用的服務化帶來更多的規範與抽象,服務路由中需要考慮單元間的調用,跨機房調用等更多場景。這裡主要希望表達的是 LDC 架構給 RPC 調用帶來更高的複雜度。

| 服務化痛點

中間件版本更新

在上面介紹背景時,有介紹到目前 LDC 架構下服務調用的複雜度,這些複雜度目前是直接展現在應用的代碼中。對于業務同學來講,一個應用的關注重點是如何實作業務邏輯,至于高可用、容災等能力更多是整體架構層面會考慮的點。應用内通過引入 RPC 的 jar 包即可獲得 LDC 架構下服務調用各種能力的支撐,帶來便利的同時也可以看到這種模式的缺點:

螞蟻科技 Service Mesh 落地實踐與挑戰

圖4. APP 業務與 SDK 組成部分

應用内除業務邏輯之外,由中間件的 SDK 引入大量外部依賴,來完成服務發現、路由尋址、負載均衡、限流熔斷、序列化、通訊等能力,每個元件的引入都可能帶來穩定性風險,以及更高的更新成本。

螞蟻科技 Service Mesh 落地實踐與挑戰

圖5. SDK 内不同能力對應的依賴

根據目前 SOFARPC 在内部的版本舉例,服務發現依賴 SOFARegistry 的用戶端做 IDC 内的服務發現,依賴 Antvip 做跨 IDC 的服務發現,ZoneClient 內建 LDC 架構的單元化資訊,路由尋址需要根據請求的入參計算目前 Zone 然後确定調用目标,限流熔斷依賴 Guardian 元件,通訊協定與序列化協定相對穩定,變更較少。僅為了完成服務調用,應用需要額外引入 7+ 用戶端包。

每年雙 11 需要涉及到架構調整時:比如支援彈性架構,需要做很多中間件用戶端的版本更新來支撐更優的架構,對于業務同學來講,這些更新是很耗費精力的,拿 200 個核心應用舉例,每個應用更新中間件版本經過研發、測試、再到部署預發、灰階、生産等環境需要 5個人日的話,200 個核心應用中間件更新需要耗費 1000 人日,如果這部分時間可以節省出來,每年架構更新可以節約大量人力資源。

跨語言通訊

螞蟻科技發展至今,内部業務百花齊放,搜尋推薦、人工智能、安全等各種業務使用到的技術棧非常多樣化,跨語言的服務通訊能力也十分重要。早在幾年前,Java 之外規模最大的就是 NodeJS 應用,為了讓 Java 和 NodeJS 應用之間可以複用螞蟻科技内部的各種中間件和基礎設施,前端團隊使用 NodeJS 逐漸重寫了各種中間件用戶端,讓整個 NodeJS 和 Java 體系可以完美互通。

螞蟻科技 Service Mesh 落地實踐與挑戰

圖6. Java 與 NodeJS 互調

中間件 SDK 跨語言重寫與維護成本極高,随着語言種類的增多,跨語言通訊的訴求也越來越多。

螞蟻科技 Service Mesh 落地實踐與挑戰

圖7. 多語言場景

Java, NodeJS, Go, Python, C++ 等,5+ 語言,中間件 SDK 全部重寫成本極高。這些問題不得不激勵我們尋找更優的解法。

| 解決痛點

SDK 能力下沉

螞蟻科技 Service Mesh 落地實踐與挑戰

圖8. SDK 瘦身并下沉能力至 Sidecar

依然以上述 RPC SDK 舉例,SDK 中的能力我們可以根據穩定性與不可剝離等特性來看,哪些是可以從應用中抽出來的,盡量把 SDK 做薄,做的足夠穩定無需變更,那麼更新成本将不複存在。

螞蟻科技 Service Mesh 落地實踐與挑戰

圖9. SDK 與 Sidecar 對應的依賴

RPC SDK 中的服務發現、路由尋址、限流熔斷等特性,是更易于變更的,我們将這部分能力下沉至獨立的 Sidecar 中,可以複用這部分能力,讓多語言的 SDK 隻實作最基本的序列化與通訊協定,而這些能力是很輕量且易于實作的。這裡的 Sidecar 我們是希望它作為獨立程序存在,和業務應用的程序剝離,并和業務應用的更新解耦開來,實作業務和基礎設施并行發展,互不幹擾的願景。

螞蟻科技 Service Mesh 落地實踐與挑戰

圖10. RPC 消息與資料源能力下沉

除了 RPC 通訊,我們還可以下沉消息、資料源等能力至 Sidecar 中,業務應用可以越來越薄,SDK 實作成本也降低到可接受的程度,基礎設施層與業務剝離,雙方均可獨立演進。

| 落地架構

整體架構

螞蟻科技 Service Mesh 落地實踐與挑戰

圖11. Mesh 落地架構

不同于開源的 Istio 體系,螞蟻科技内部版 Service Mesh 落地優先考慮資料面的實作與落地,控制面在逐漸建設中,整體的架構上看,我們使用資料面直接和内部的各種中間件服務端對接,來完成 RPC、消息等能力的下沉,給業務應用減負。由上圖可以看出,我們将不同的 Sidecar 與業務應用編排在同一個 Pod 中,App 與 SOFAMosn 直接通訊,SOFAMosn 來負責目标接口的服務發現、路由尋址,并且由 SOFAMosn 内置的安全子產品來做應用間調用的加密鑒權。通過 DBMesh 的 Sidecar 來實作資料層的下沉,App 不在需要與多個資料源建立連接配接,隻需要連接配接本 Pod 内的 DBMesh 即可完成資料層調用,資料庫的使用者名、密碼、分庫分表規則等均不再需要關心。

圖中名詞解析:

  • ConfigServer:配置中心,負責各種中繼資料配置、動态開關等
  • Registry:服務注冊中心,負責 IDC 内服務發現
  • AntVip:類 DNS 解析的産品,可通過域名解析一組目标位址,用于跨 IDC 服務發現
  • MQ:消息中心服務端,用于收發消息

落地資料

螞蟻科技 Service Mesh 落地實踐與挑戰

圖12. 落地 CPU 資料

目前這套架構已經在支付核心鍊路中做試點,618 大促 Mesh 化應用對比無 Mesh 化應用 CPU 損耗增長 1.7%,單筆交易整體耗時增長 5ms。CPU 增長是由于多出一個程序,請求增加一條之後,RT 會有穩定的小幅增長,但這些成本相比于整體架構帶來的紅利,微乎其微,并且針對整個資料面的持續優化是有望逐漸減少資源占用,提升資源使用率。

降低打擾度

中間件能力下沉在架構上看是可行的,實際落地如何做到無打擾的在奔跑的火車上換輪子,低打擾是一個非常重要的考量點。借助于 Kubernetes 的優秀實踐,将業務容器與 Sidecar 容器編排在同一個 Pod 中是比較合理的架構,Sidecar 與業務容器互不幹擾,互相更新均可做到雙方無感。

螞蟻科技 Service Mesh 落地實踐與挑戰

圖13. 落地方式

我們為了讓業務應用更新盡可能如絲般順滑,主要做了如下優化方案:

1. 無感鏡像化

螞蟻科技内部還有部分應用未完成鏡像化,或者說以富容器的方式來使用鏡像化,這種方式也是在逐漸淘汰的過程中,為了讓業務更順滑的鏡像化,PAAS 平台關聯整個研發體系,将應用的打包過程通過自動生成 Dockerfile 的方式主動幫使用者完成鏡像化。做到使用者無感覺鏡像化改造。

2. 低感 Mesh 化

鏡像化完成之後,想要借助 Pod 模型将應用的容器和 SOFAMosn 的容器部署在一起,我們需要将底層資源管理與排程全部替換到 Kubernetes 體系。然後在 PAAS 上給 Mesh 化的應用增加辨別,通過 Kubernetes 識别這些辨別并主動注入 SOFAMosn sidecar 來完成應用的 Mesh 化接入。

3. 無感 Sidecar 更新

Sidecar 與業務程序獨立後,還有一個核心的訴求就是希望 Sidecar 可以獨立更新,為了讓 Sidecar 的更新盡量對生産做到無打擾,我們實作了 SOFAMosn 平滑更新的 Operator,通過對運作中 SOFAMosn 的連接配接遷移,實作整個更新過程應用完全無感覺。當然這裡面包含着很多挑戰,後面我們會詳細介紹。

| 落地挑戰

Sidecar 平滑更新

目前我們已經實作 SOFAMosn 的平滑更新能力,SOFAMosn 的主要能力是 RPC 和 消息的通訊代理,平滑更新的目的是業務 App 程序不重新開機,業務請求不中斷,完成 SOFAMosn 的版本更新。

螞蟻科技 Service Mesh 落地實踐與挑戰

圖14. SOFAMosn 平滑更新

由于SOFAMosn 與應用是獨立的 container,如上圖描述,SOFAMosn 的更新是需要做到 Pod 内鏡像的熱替換,這種熱替換能力必須要保障幾點:

  1. Pod 不會被重建,應用程序始終正常運作
  2. 鏡像的替換不會影響運作中的流量
  3. 鏡像替換後整個 Pod 描述需要進行更新

為了達成以上目标,我們通過對 Kubernetes 的改造以及自定義 Operator 來完成以上更新的處理。處理流程如下:

螞蟻科技 Service Mesh 落地實踐與挑戰

圖15. SOFAMosn 平滑更新流程

在不考慮多鏡像間做平滑更新的場景下,通過 Fork 程序,可以繼承父程序的 FD 來完成長連接配接的遷移,實作無損熱更新。SOFAMosn 以鏡像化的方式運作後,平滑更新的難度極大增加。整個平滑更新的難點在于如何讓不同容器内的SOFAMosn 程序可互相感覺并可完成連接配接遷移。

下面我們來看下SOFAMosn 更新過程中,如何保障流量無損:

螞蟻科技 Service Mesh 落地實踐與挑戰

圖16. 正常流量走向

SOFAMosn 處理的正常流量分為入口流量和出口流量,Client 可以看成和SOFAMosn 部署在同 Pod 内的 App,Server 可以是請求調用的目标服務提供方,可以是一個 App 也可以是被調用 App 側的SOFAMosn。當一筆請求從 Client 發至 Server 時,中間會經過兩條長連接配接:TCP1 和 TCP2,SOFAMosn 會記錄這筆請求對應的 ConnectionID,來完成請求的發起與響應。

螞蟻科技 Service Mesh 落地實踐與挑戰

圖16. 正向流量遷移

當新的 Mosn 容器被啟動時,Mosn 會根據本地的 Domain Socket 來嘗試發送請求,當另一個 Mosn 程序存在時,Mosn V1 和 Mosn V2 進入熱更新模式,Mosn V1 會将已存在連接配接的 FD 和已讀出的資料包 通過 Domain Socket 發送至 Mosn V2 同時 V1 将不會再從已遷移的 FD 中讀取資料,FD 遷移完成所有流量将會直接由 Mosn V2 來處理。

螞蟻科技 Service Mesh 落地實踐與挑戰

圖17. 逆向流量遷移

Mosn V1 和 Mosn V2 進入熱更新模式之後,可能會存在 Mosn V1 已經将請求發給 Server 後 Server 還沒有來得及響應的情況,這種場景 Mosn V1 在遷移 FD 給 Mosn V2 時,Mosn V2 會在 FD 接管到之後的 ConnectionID 傳回給 Mosn V1,當 Mosn V1 收到 Server 傳回的 Response 之後,會将這筆請求通過 Domain Socket 發送給 Mosn V2,然後 Mosn V2 根據 ConnectionId 即可找到 TCP1 的連接配接,然後響應給 Client。

極緻性能優化

螞蟻科技 Service Mesh 落地實踐與挑戰

圖18. 請求合并寫

SOFAMosn 的核心網絡模型是完全自實作的,我們在整個網絡層做了非常多的優化,通過 golang 的 writev 我們把多筆請求合并成一次寫,降低 sys.call 的調用,提升整體的性能與吞吐。同時在使用 writev 的過程中,有發現 golang 對 writev 的實作有 bug,會導緻部分記憶體無法回收,我們給 golang 送出 PR 修複此問題,已被接受:https://github.com/golang/go/pull/32138 

其他優化點還有很多,不再一一較長的描述,僅供思路參考,如:

  • SOFAMosn 日志異步化,避免磁盤問題對 SOFAMosn 轉發性能的影響
  • Route 路由結果緩存,空間換時間,提升吞吐
  • 接近 90% 記憶體複用,盡量避免位元組拷貝
  • Cluster 懶加載,提升 SOFAMosn 啟動速度
  • 通訊協定層優化,低版本協定針對性更新,降低解包成本

| 演進方向

螞蟻科技 Service Mesh 落地實踐與挑戰

圖19. 演進方向控制面結合

Service Mesh 的控制面建設我們也在規劃中逐漸向前推進,希望能統一資料面和控制面的互動模型,控制面盡量遵循 SMI 标準,增加對 TCP 協定的描述支援,逐漸增強 SOFAMosn 作為資料面的穩定性,減少變更頻率,用更通用的模型來描述服務發現、服務治理等場景,DBMesh 也會基于 XDS 做配置的下發,統一又控制面收口資料下發通道。這裡控制面直接對接中間件的服務端是基于性能與容量考慮,螞蟻科技内部的服務發現資料達單機房千萬級别,使用 Kubernetes 的 ETCD 無法承載如此巨大的資料量,需要又控制面做橋梁并分片服務于不同的資料面。

螞蟻科技 Service Mesh 落地實踐與挑戰

圖20. 産品化模型

接下來還會有完整的産品層建設,借助于 Mesh 化架構的思想,更多的能力希望通過下沉至 Sidecar 的方式來拿到架構更新帶來的紅利。Mesh 的産品層将會包括多種 Mesh 資料面形态的 Metrics 采集、監控大盤,控制面的統一對外途徑,屏蔽外部系統與 Mesh 的互動複雜度,統一控制面與資料面互動協定,通過完善的運維體系建設,提升 Mesh 模式下的 Sidecar 灰階更新能力,做到對應用無打擾且穩定無人值守即可完成版本更新的目的。

| 總結

總結一下全文在 Service Mesh 領域的落地實踐,可以歸納為以下六點:

  • 應用層與基礎設施層分離
  • 基礎設定層一次編寫多處複用
  • 資料面通過能力平移優先落地
  • 降低打擾度提升落地效率
  • 控制面建設統一資料面配置模型
  • 性能、穩定性、可觀測性持續優化

本文介紹了螞蟻科技在 Service Mesh 落地的演進過程以及相關痛點的解決方式,希望可以通過我們的實際經曆來為讀者帶來一些不同與社群主流方案的演進思考。

繼續閱讀