
揭秘 2019 Service Mesh 雙十一大考
螞蟻金服很早開始關注 Service Mesh,并在 2018 年發起 ServiceMesher 社群,目前已有 4000+ 開發者在社群活躍。在技術應用層面,Service Mesh 的場景已經渡過探索期,今年已經全面進入深水區探索。
2019 年的雙十一是我們的重要時刻,我們進行了大規模的落地。作為技術人能面對世界級的流量挑戰,是非常緊張和興奮的。當 Service Mesh 遇到雙十一又會迸發出怎樣的火花?螞蟻金服的 LDC 架構繼續演進的過程中,Service Mesh 要承載起哪方面的責任?讓我們一起來揭秘螞蟻金服 Service Mesh 雙十一實戰。
Service Mesh 基礎概念
Istio 清晰的描述了 Service Mesh 最核心的兩個概念:資料面與控制面。資料面負責做網絡代理,在服務請求的鍊路上做一層攔截與轉發,可以在鍊路中做服務路由、鍊路加密、服務鑒權等,控制面負責做服務發現、服務路由管理、請求度量(放在控制面頗受争議)等。
Service Mesh 帶來的好處不再贅述,我們來看下螞蟻金服的資料面和控制面産品:
- 資料面:SOFAMosn。螞蟻金服使用 Golang 研發的高性能網絡代理,作為 Service Mesh 的資料面,承載了螞蟻金服雙十一海量的核心應用流量。
- 控制面:SOFAMesh。Istio 改造版,落地過程中精簡為 Pilot 和 Citadel,Mixer 直接內建在資料面中避免多一跳的開銷。
雙十一落地情況概覽
今年,螞蟻金服的核心應用全面接入 SOFAMosn,生産 Mesh 化容器幾十萬台,雙十一峰值 SOFAMosn 承載資料規模數千萬 QPS,SOFAMosn 轉發平均處理耗時 0.2ms。
在如此大規模的接入場景下,我們面對的是極端複雜的場景,同時需要多方全力合作,更要保障資料面的性能穩定性滿足大促訴求,整個過程極具挑戰。
同時,Service Mesh 的落地也是一個跨團隊合作的典範案例,集合了核心、RPC、消息、無線網關、控制面、安全、運維、測試等團隊的精誠合作,接下來我們會按照以上幾個子產品來解析 Service Mesh 的雙十一落地情況,更多解析關注本号。
本文為《螞蟻金服 Service Mesh 落地實踐系列》第一篇 - 核心篇,作者:田陽(花名:烈元),螞蟻金服技術專家,專注于高性能網絡伺服器研發,Tengine 開源項目核心成員,螞蟻金服開源 SOFAMosn 項目核心成員。
基礎能力建設
SOFAMosn 的能力大圖
SOFAMosn 主要劃分為如下子產品,包括了網絡代理具備的基礎能力,也包含了 XDS 等雲原生能力。
業務支援
SOFAMosn 作為底層的高性能安全網絡代理,支撐了 RPC,MSG,GATEWAY 等業務場景。
IO 模型
SOFAMosn 支援兩種 IO 模型,一個是 Golang 經典模型,goroutine-per-connection;一個是 RawEpoll 模型,也就是 Reactor 模式,I/O 多路複用(I/O multiplexing) + 非阻塞 I/O(non-blocking I/O)的模式。
在螞蟻金服内部的落地場景,連接配接數不是瓶頸,都在幾千或者上萬的量級,我們選擇了 Golang 經典模型。而對于接入層和網關有大量長連結的場景,更加适合于 RawEpoll 模型。
協程模型
- 一條 TCP 連接配接對應一個 Read 協程,執行收包,協定解析;
- 一個請求對應一個 worker 協程,執行業務處理,proxy 和 Write 邏輯;
正常模型一個 TCP 連接配接将有 Read/Write 兩個協程,我們取消了單獨的 Write 協程,讓 workerpool 工作協程代替,減少了排程延遲和記憶體占用。
能力擴充
協定擴充
SOFAMosn 通過使用同一的編解碼引擎以及編/解碼器核心接口,提供協定的 plugin 機制,包括支援:
- SOFARPC;
- HTTP1.x/HTTP2.0;
- Dubbo;
NetworkFilter 擴充
SOFAMosn 通過提供 network filter 注冊機制以及統一的 packet read/write filter 接口,實作了 Network filter 擴充機制,目前支援:
- TCP proxy;
- Fault injection;
StreamFilter 擴充
SOFAMosn 通過提供 stream filter 注冊機制以及統一的 stream send/receive filter 接口,實作了 Stream filter 擴充機制,包括支援:
- 流量鏡像;
- RBAC鑒權;
TLS 安全鍊路
作為金融科技公司,資金安全是最重要的一環,鍊路加密又是其中最基礎的能力,在 TLS 安全鍊路上我們進行了大量的調研測試。
通過測試,原生的 Go 的 TLS 經過了大量的彙編優化,在性能上是 Nginx(OpenSSL)的80%,Boring 版本的 Go(使用 cgo 調用 BoringSSL) 因為 cgo 的性能問題, 并不占優勢,是以我們最後選型原生 Go 的 TLS,相信 Go Runtime 團隊後續會有更多的優化,我們也會有一些優化計劃。
- go 在 RSA 上沒有太多優化,go-boring(CGO)的能力是 go 的1倍;
- p256 在 go 上有彙編優化,ECDSA 優于go-boring;
- 在 AES-GCM 對稱加密上,go 的能力是 go-boring 的20倍;
- 在 SHA、MD 等 HASH 算法也有對應的彙編優化;
為了滿足金融場景的安全合規,我們同時也對國産密碼進行了開發支援,這個是 Go Runtime 所沒有的。雖然目前的性能相比國際标準 AES-GCM 還是有一些差距,大概是 50%,但是我們已經有了後續的一些優化計劃,敬請期待。
平滑更新能力
為了讓 SOFAMosn 的釋出對應用無感覺,我們調研開發了平滑更新方案,類似 Nginx 的二進制熱更新能力,但是有個最大的差別就是 SOFAMosn 老程序的連接配接不會斷,而是遷移給新的程序,包括底層的 socket FD 和上層的應用資料,保證整個二進制釋出過程中業務不受損,對業務無感覺。除了支援 SOFARPC、Dubbo、消息等協定,我們還支援 TLS 加密鍊路的遷移。
容器更新
基于容器平滑更新 SOFAMosn 給了我們很多挑戰,我們會先注入一個新的 SOFAMosn,然後他會通過共享卷的 UnixSocket 去檢查是否存在老的 SOFAMosn,如果存在就和老的 SOFAMosn 進行連接配接遷移,然後老的 SOFAMosn 退出。這一塊的細節較多,涉及 SOFAMosn 自身和 Operator 的互動。
SOFAMosn 的連接配接遷移
連接配接遷移的核心主要是核心 Socket 的遷移和應用資料的遷移,連接配接不斷,對使用者無感覺。
SOFAMosn 的 metric 遷移
我們使用了共享記憶體來共享新老程序的 metric 資料,保證在遷移的過程中 metric 資料也是正确的。
記憶體複用機制
- 基于 sync.Pool;
- slice 複用使用 slab 細粒度,提高複用率;
- 常用結構體複用;
線上複用率可以達到90%以上,當然 sync.Pool 并不是銀彈,也有自己的一些問題,但是随着 Runtime 對 sync.Pool 的持續優化,比如 go1.13 就使用 lock-free 結構減少鎖競争和增加了 victim cache 機制,以後會越來越完善。
XDS(UDPA)
支援雲原生統一資料面 API,全動态配置更新。
前期準備
性能壓測和優化
在上線前的準備過程中,我們在灰階環境針對核心收銀台應用進行了大量的壓測和優化,為後面的落地打下了堅實的基礎。
從線下環境到灰階環境,我們遇到了很多線下沒有的大規模場景,比如單執行個體數萬後端節點,數千路由規則,不僅占用記憶體,對路由比對效率也有很大影響,比如海量高頻的服務釋出注冊也對性能和穩定性有很大挑戰。
整個壓測優化過程曆時五個月,從最初的 CPU 整體增加20%,RT 每跳增加 0.8ms, 到最後 CPU 整體增加 6%,RT 每跳增加了 0.2ms,記憶體占用峰值優化為之前的 1/10 。
整體增加CPU | 每跳RT | 記憶體占用峰值 | |
---|---|---|---|
優化前 | 20% | 0.8ms | 2365M |
優化後 | 6% | 0.2ms | 253M |
- 部分優化措施
在 618 大促時,我們上線了部分核心鍊路應用,CPU 損耗最多增加 1.7%,有些應用由于邏輯從 Java 遷移到 Go,CPU 損耗還降低了,有 8% 左右。延遲方面平均每跳增加 0.17ms,兩個合并部署系統全鍊路增加 5~6ms,有 7% 左右的損耗。
在後面單機房上線 SOFAMosn,在全鍊路壓測下,SOFAMosn 的整體性能表現更好,比如交易付款帶 SOFAMosn 比不帶 SOFAMosn 的 RT 還降低了 7.5%。
SOFAMosn 做的大量核心優化和 Route Cache 等業務邏輯優化的下沉,更快帶來了架構的紅利。
Go 版本選擇
版本的更新都需要做一系列測試,新版本并不是都最适合你的場景。我們項目最開始使用的 Go 1.9.2,在經過一年疊代之後,我們開始調研當時 Go 的最新版 1.12.6,我們測試驗證了新版很多好的優化,也修改了記憶體回收的預設政策,更好的滿足我們的項目需求。
- GC 優化,減少長尾請求
新版的自我搶占(self-preempt)機制,将耗時較長 GC 标記過程打散,來換取更為平滑的GC表現,減少對業務的延遲影響。
https://go-review.googlesource.com/c/go/+/68574/ https://go-review.googlesource.com/c/go/+/68573/Go 1.9.2
Go 1.12.6
- 記憶體回收政策
在 Go1.12,修改了記憶體回收政策,從預設的 MADV_DONTNEED 修改為了 MADV_FREE,雖然是一個性能優化,但是在實際使用中,通過測試并沒有大的性能提升,但是卻占用了更多的記憶體,對監控和問題判斷有很大的幹擾,我們通過 GODEBUG=madvdontneed=1 恢複為之前的政策,然後在 issue 裡面也有相關讨論,後續版本可能也會改動這個值。
runtime: use MADV_FREE on Linux if available使用 Go1.12 預設的 MADV_FREE 政策 ,Inuse 43M, 但是 Idle 卻有 600M,一直不能釋放。
Go Runtime Bug 修複
在前期灰階驗證時,SOFAMosn 線上出現了較嚴重的記憶體洩露,一天洩露了1G 記憶體,最終排查是 Go Runtime 的 Writev 實作存在缺陷,導緻 slice 的記憶體位址被底層引用,GC 不能釋放。
我們給 Go 官方送出了 Bugfix,已合入 Go 1.13最新版。
internal/poll: avoid memory leak in Writev後序
SOFAMosn 在螞蟻金服經曆了雙十一的大考,後續我們還有更多的技術演進和支撐場景,歡迎有興趣的同學加入我們。
SOFAMosn:
https://github.com/sofastack/sofa-mosn更多關于螞蟻金服 Service Mesh 的雙十一落地情況解析,請繼續關注本号喲~