螞蟻金服 Service Mesh 落地實踐與挑戰 | GIAC 實錄

本文整理自 GIAC(GLOBAL INTERNET ARCHITECTURE CONFERENCE)全球互聯網架構大會,螞蟻金服平臺數據技術事業羣技術專家石建偉(花名:卓與)的分享。分享基於 Service Mesh 的理念,結合螞蟻金服內部實際場景,將中間件、數據層、安全層等能力從應用中剝離出來後下沉至獨立的 Sidecar SOFAMosn 中,結合 Kubernetes 運維體系,提供應用無感知的狀況下升級基礎設施層能力的案例。前端

12.jpg

本次分享將從以以下次序展開進行:git

image.png

螞蟻金服當前的服務化現狀

在看螞蟻金服的服務化架構以前咱們先從一個簡單的服務化調用示例提及,下圖是 SOFARPC 基本原理:github

image.png
圖1. SOFARPC 基本原理golang

咱們從上圖能夠看出,構建一個服務化框架須要有服務註冊中心,有服務定義,調用方和服務提供方使用相同的服務定義來互相通信。經過服務註冊中心,調用方能夠直接訂閱到服務提供方的地址,採用點對點的方式直接發起請求。客戶端內可實現服務發現、路由尋址、負載均衡、限流熔斷等能力來加強服務通信能力。經過咱們開源的 SOFARPC、SOFARegistry、SOFABoot,用戶已經能夠直接構建起微服務體系,助力業務發展。數據庫

螞蟻金服發展至今,雙 11 系統須要應對的交易洪峯逐年遞增:緩存

image.png
圖2. 歷年雙 11 交易額與峯值數據安全

每秒 26.5 萬筆交易是 2017 年雙 11 的峯值數據,這個數據背後有很是複雜的架構支持,LDC 單元化架構是螞蟻金服沉澱多年的核心架構,依靠這個架構實現每一年峯值交易量飛速增加下系統依然能平滑渡過。咱們來簡要看下 LDC 架構:性能優化

image.png
圖3. LDC 架構示例網絡

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

服務化痛點

中間件版本升級

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

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


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

image.png
圖5. SDK 內不一樣能力對應的依賴


根據目前 SOFARPC 在內部的版本舉例,服務發現依賴 SOFARegistry 的客戶端作 IDC 內的服務發現,依賴 Antvip 作跨 IDC 的服務發現,ZoneClient 集成 LDC 架構的單元化信息,路由尋址須要根據請求的入參計算目前 Zone 而後肯定調用目標,限流熔斷依賴 Guardian 組件,通信協議與序列化協議相對穩定,變動較少。僅爲了完成服務調用,應用須要額外引入 7+ 客戶端包。

圖片2.png

每一年雙 11 須要涉及到架構調整時:好比支持彈性架構,須要作不少中間件客戶端的版本升級來支撐更優的架構,對於業務同窗來說,這些升級是很耗費精力的,拿 200 個核心應用舉例,每一個應用升級中間件版本通過研發、測試、再到部署預發、灰度、生產等環境須要 5我的日的話,200 個核心應用中間件升級須要耗費 1000 人日,若是這部分時間能夠節省出來,每一年架構升級能夠節約大量人力資源。

跨語言通信

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

image.png
圖6. Java 與 NodeJS 互調

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

圖片3.png
圖7. 多語言場景

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

解決痛點

SDK 能力下沉


image.png
圖8. SDK 瘦身並下沉能力至 Sidecar


依然以上述 RPC SDK 舉例,SDK 中的能力咱們能夠根據穩定性與不可剝離等特性來看,哪些是能夠從應用中抽出來的,儘可能把 SDK 作薄,作的足夠穩定無需變動,那麼升級成本將不復存在。


image.png
圖9. SDK 與 Sidecar 對應的依賴


RPC SDK 中的服務發現、路由尋址、限流熔斷等特性,是更易於變動的,咱們將這部分能力下沉至獨立的 Sidecar 中,能夠複用這部分能力,讓多語言的 SDK 只實現最基本的序列化與通信協議,而這些能力是很輕量且易於實現的。這裏的 Sidecar 咱們是但願它做爲獨立進程存在,和業務應用的進程剝離,並和業務應用的升級解耦開來,實現業務和基礎設施並行發展,互不干擾的願景。


image.png
圖10. RPC 消息與數據源能力下沉
除了 RPC 通信,咱們還能夠下沉消息、數據源等能力至 Sidecar 中,業務應用能夠愈來愈薄,SDK 實現成本也下降到可接受的程度,基礎設施層與業務剝離,雙方都可獨立演進。

落地架構

總體架構

image.png
圖11. Mesh 落地架構
不一樣於開源的 Istio 體系,螞蟻金服內部版 Service Mesh 落地優先考慮數據面的實現與落地,控制面在逐步建設中,總體的架構上看,咱們使用數據面直接和內部的各類中間件服務端對接,來完成 RPC、消息等能力的下沉,給業務應用減負。由上圖能夠看出,咱們將不一樣的 Sidecar 與業務應用編排在同一個 Pod 中,App 與 Mosn 直接通信,Mosn 來負責目標接口的服務發現、路由尋址,而且由 Mosn 內置的安全模塊來作應用間調用的加密鑑權。經過 DBMesh 的 Sidecar 來實現數據層的下沉,App 不在須要與多個數據源創建鏈接,只須要鏈接本 Pod 內的 DBMesh 便可完成數據層調用,數據庫的用戶名、密碼、分庫分表規則等均再也不須要關心。


圖中名詞解析:


ConfigServer:配置中心,負責各類元數據配置、動態開關等。
Registry:服務註冊中心,負責 IDC 內服務發現。
AntVip:類 DNS 解析的產品,可經過域名解析一組目標地址,用於跨 IDC 服務發現。
MQ:消息中心服務端,用於收發消息。

落地數據


image.png
圖12. 落地 CPU 數據
目前這套架構已經在支付核心鏈路中作試點,618 大促 Mesh 化應用對比無 Mesh 化應用 CPU 損耗增加 1.7%,單筆交易總體耗時增加 5ms。CPU 增加是因爲多出一個進程,請求增長一條以後,RT 會有穩定的小幅增加,但這些成本相比於總體架構帶來的紅利,微乎其微,而且針對整個數據面的持續優化是有望逐步減小資源佔用,提高資源利用率。

下降打擾度

中間件能力下沉在架構上看是可行的,實際落地如何作到無打擾的在奔跑的火車上換輪子,低打擾是一個很是重要的考量點。藉助於 Kubernetes 的優秀實踐,將業務容器與 Sidecar 容器編排在同一個 Pod 中是比較合理的架構,Sidecar 與業務容器互不干擾,互相升級都可作到雙方無感。

圖片4.png
圖13. 落地方式


咱們爲了讓業務應用升級儘量如絲般順滑,主要作了以下優化方案:

1. 無感鏡像化

螞蟻金服內部還有部分應用未完成鏡像化,或者說以富容器的方式來使用鏡像化,這種方式也是在逐步淘汰的過程當中,爲了讓業務更順滑的鏡像化,PAAS 平臺聯動整個研發體系,將應用的打包過程經過自動生成 Dockerfile 的方式主動幫用戶完成鏡像化。作到用戶無感知鏡像化改造。

2. 低感 Mesh 化

鏡像化完成以後,想要藉助 Pod 模型將應用的容器和 Mosn 的容器部署在一塊兒,咱們須要將底層資源管理與調度所有替換到 Kubernetes 體系。而後在 PAAS 上給 Mesh 化的應用增長標識,經過 Kubernetes 識別這些標識並主動注入 Mosn sidecar 來完成應用的 Mesh 化接入。

3. 無感 Sidecar 升級

Sidecar 與業務進程獨立後,還有一個核心的訴求就是但願 Sidecar 能夠獨立升級,爲了讓 Sidecar 的升級儘可能對生產作到無打擾,咱們實現了 Mosn 平滑升級的 Operator,經過對運行中 Mosn 的鏈接遷移,實現整個升級過程應用徹底無感知。固然這裏麪包含着不少挑戰,後面咱們會詳細介紹。

落地挑戰

Sidecar 平滑升級

目前咱們已經實現 Mosn 的平滑升級能力,Mosn 的主要能力是 RPC 和 消息的通信代理,平滑升級的目的是業務 App 進程不重啓,業務請求不中斷,完成 Mosn 的版本升級。

image.png
圖14. Mosn 平滑升級

因爲 Mosn 與應用是獨立的 container,如上圖描述,Mosn 的升級是須要作到 Pod 內鏡像的熱替換,這種熱替換能力必需要保障幾點:

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

爲了達成以上目標,咱們經過對 Kubernetes 的改造以及自定義 Operator 來完成以上升級的處理。處理流程以下:

image.png
圖15. Mosn 平滑升級流程

在不考慮多鏡像間作平滑升級的場景下,經過 Fork 進程,能夠繼承父進程的 FD 來完成長鏈接的遷移,實現無損熱升級。Mosn 以鏡像化的方式運行後,平滑升級的難度極大增長。整個平滑升級的難點在於如何讓不一樣容器內的 Mosn 進程可互相感知並可完成鏈接遷移。


下面咱們來看下 Mosn 升級過程當中,如何保障流量無損:


image.png
圖16. 正常流量走向


Mosn 處理的正常流量分爲入口流量和出口流量,Client 能夠當作和 Mosn 部署在同 Pod 內的 App,Server 能夠是請求調用的目標服務提供方,能夠是一個 App 也能夠是被調用 App 側的 Mosn。當一筆請求從 Client 發至 Server 時,中間會通過兩條長鏈接:TCP1 和 TCP2,Mosn 會記錄這筆請求對應的 ConnectionID,來完成請求的發起與響應。


image.png
圖16. 正向流量遷移


當新的 Mosn 容器被啓動時,Mosn 會根據本地的 Domain Socket 來嘗試發送請求,當另外一個 Mosn 進程存在時,Mosn V1 和 Mosn V2 進入熱升級模式,Mosn V1 會將已存在鏈接的 FD 和已讀出的數據包 經過 Domain Socket 發送至 Mosn V2 同時 V1 將不會再從已遷移的 FD 中讀取數據,FD 遷移完成全部流量將會直接由 Mosn V2 來處理。


image.png
圖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。

極致性能優化

image.png
圖18. 請求合併寫


Mosn 的核心網絡模型是徹底自實現的,咱們在整個網絡層作了很是多的優化,經過 golang 的 writev 咱們把多筆請求合併成一次寫,下降 sys.call 的調用,提高總體的性能與吞吐。同時在使用 writev 的過程當中,有發現 golang 對 writev 的實現有 bug,會致使部份內存沒法回收,咱們給 golang 提交 PR 修復此問題,已被接受:https://github.com/golang/go/pull/32138 


其餘優化點還有不少,再也不一一詳細描述,僅供思路參考,如:

  • Mosn 日誌異步化,避免磁盤問題對 Mosn 轉發性能的影響
  • Route 路由結果緩存,空間換時間,提高吞吐
  • 接近 90% 內存複用,儘可能避免字節拷貝
  • Cluster 懶加載,提高 Mosn 啓動速度
  • 通信協議層優化,低版本協議針對性升級,下降解包成本

演進方向

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


Service Mesh 的控制面建設咱們也在規劃中逐步向前推動,但願能統一數據面和控制面的交互模型,控制面儘可能遵循 SMI 標準,增長對 TCP 協議的描述支持,逐步加強 Mosn 做爲數據面的穩定性,減小變動頻率,用更通用的模型來描述服務發現、服務治理等場景,DBMesh 也會基於 XDS 作配置的下發,統一又控制面收口數據下發通道。這裏控制面直接對接中間件的服務端是基於性能與容量考慮,螞蟻金服內部的服務發現數據達單機房千萬級別,使用 Kubernetes 的 ETCD 沒法承載如此巨大的數據量,須要又控制面作橋樑並分片服務於不一樣的數據面。


image.png
圖20. 產品化模型


接下來還會有完整的產品層建設,藉助於 Mesh 化架構的思想,更多的能力但願經過下沉至 Sidecar 的方式來拿到架構升級帶來的紅利。Mesh 的產品層將會包括多種 Mesh 數據面形態的 Metrics 採集、監控大盤,控制面的統一對外途徑,屏蔽外部系統與 Mesh 的交互複雜度,統一控制面與數據面交互協議,經過完善的運維體系建設,提高 Mesh 模式下的 Sidecar 灰度升級能力,作到對應用無打擾且穩定無人值守便可完成版本升級的目的。

總結

總結一下全文在 Service Mesh 領域的落地實踐,能夠概括爲如下六點:

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

本文介紹了螞蟻金服在 Service Mesh 落地的演進過程以及相關痛點的解決方式,但願能夠經過咱們的實際經從來爲讀者帶來一些不一樣與社區主流方案的演進思考。

本次分享完整 PPT 下載地址:下載地址

在 KubeCon&CloudNativeCon&Open Source Summit 上,SOFAStack 進行了全天的 Workshop,其中提供了 Service Mesh 實踐 Demo,咱們將在近期同步,請關注下圖二維碼噢~

公衆號尾圖 0605-1.png

相關文章
相關標籤/搜索