本文作者:朵曉東,花名奕杉,螞蟻金服高階技術專家,專注雲端計算技術及產品。Apache Kylin 創始團隊核心成員,螞蟻金融雲 PaaS 創始團隊核心成員,Antstack 網路產品負責人,SOFAMesh 創始團隊核心成員。
專案在這裡:https://github.com/alipay/sofa-mosn
本文是基於作者在 Service Mesh Meetup #2 北京的主題分享《螞蟻金服 Service Mesh 資料平面 SOFAMosn 深層解密》部分內容所整理,完整內容見文末的直播回放
前言
今天給大家帶來的分享內容是螞蟻金服 Service Mesh 資料平面 SOFAMosn 深層揭祕。
承接小劍老師在Service Mesh Meetup #1杭州的主題《大規模微服務架構下的 Service Mesh 探索之路》對 SOFAMosn 的分享,本次聚焦在資料平面在螞蟻落地的思考和探索。
背景
上一次分享小劍老師已經介紹了 SOFAMesh 的技術選型,以及我們在開源和自研方面的一些權衡。
呼應這個話題我們首先來看一下為什麼螞蟻會選擇 Service Mesh
重點歸納為 4 個方面:
螞蟻正在全面擁抱微服務,雲原生,不管是 SOFA5,還是相容 K8S 的容器平臺 Sigma 落地,Service Mesh 都是不可獲取的重要元件。
其次,螞蟻的運維體系在服務層面基於流量排程工作,比如說 LDC 架構在邏輯 zone 間的排程流量,再比如彈性伸縮,本質上也是在異構機房間排程流量,此外還有像邏輯 zone 藍綠髮布,機房容災等都需要在流量排程能力上更健壯,更靈活,更具擴充套件性。
此外,由於螞蟻的金融屬性,我們在服務鑑權等方面有更嚴格的要求,比如說國密的落地,加密卡內的證書管理,加解密等方面,不止要求更高的安全級別,還要有承載大流量的能力。同時我們看到,zero trust網路架構也在加速發展,這與我們的訴求不謀而合。
最後,螞蟻內部技術棧多樣,但多種語言體系融合仍然成本很高。
舉個例子,非 SOFA 語言與 SOFA 互通要理解配置中心,SOFARPC 的序列化等邏輯,如果在生產環境部署還要理解 LDC 路由規則,而這些共性需求都可以通過下沉到 Mesh 體系來解決。
瞭解 SOFAMesh 的同學應該知道,螞蟻選擇了使用 Golang 自研資料平面,做這個決定我們重點考慮了未來的技術選型,跨團隊研發效率,螞蟻現有技術體系,運維體系等因素;同時通過調研和驗證,Golang 版本的效能也是我們可以接受的。
接下來,我會向大家介紹由螞蟻和 UC 聯合研發的 Mesh 資料平面,我們為他取名 SOFAMosn
SOFAMesh 的整體架構
大家看到的圖示是基於 Istio 的架構,在資料平面我們使用 SOFAMosn 替代了 Envoy,同時加入了一些螞蟻實踐中摸索的改進。
0.1.0 版本的 SOFAMosn 支援了 xDS V0.4 api 核心能力,重點支援了 SOFARPC 協議,並在螞蟻內部在生產環境使用;同時支援了HTTP/1.1,HTTP/2.0的基本功能,但目前暫未在生產環境使用。
SOFAMosn 的核心設計思路
首先,將 SOFAMosn 作為代理處理的資料流劃分為4層,在入方向資料依次經過網路 IO 層,二進位制協議處理層,協議流程處理層,轉發路由處理層;出向與入向過程基本相反。
瞭解了分層的基本思路,具體介紹一下各層的具體職能:
IO 層提供了 IO 讀寫的封裝以及可擴充套件的 IO 事件訂閱機制
PROTOCOL 層提供了根據不同協議對資料進行序列化/反序列化的處理能力
STREAMING 層提供向上的協議一致性,負責 STREAM 生命週期,管理 Client / Server 模式的請求流行為,對 Client 端stream 提供池化機制等
Proxy 層提供路由選擇,負載均衡等的能力,讓前後端 stream 流轉起來。大家可以從這張圖清晰的看到單向請求流轉的過程。
瞭解了分層設計和轉發流程,我們再看下執行緒模型。從 0.1.0 版本的執行緒模型,可以看到每個連結的 IO 協程是成對出現的,讀協程負責讀取,事件機制及 Codec 邏輯,資料上升到 steam 層,具體的 stream 事件由獨立的常駐 worker 協程池負責處理。
在 0.2.0 版本中我們將會進行多核優化,讀協程將不再負責 codec 邏輯,將轉發由 codec worker pool 來進行。從發展方向上看,我們會借鑑 SEDA 的思路,將轉發流程中每一階段的處理抽象為一個 stage,通過 task queue,worker 協程池,controller 的機制來對每一個階段進行處理。從技術實現上看,Golang 實現 SEDA 機制的元件也更簡單。
SOFAMosn 的模組劃分
除了剛才介紹了 4 個核心模組,還有如路由模組負責請求的路由定址,後端管理模組負責管理後端的生命週期,健康度等。其中藍色的框是 SOFAMosn 0.1.0 會涉及到的功能模組,紅色的虛線框是我們規劃去實現,或實驗的一些topic。這方面也歡迎大家加入我們一起來建設。
最後總結一下,模組化,分層解耦是 SOFAMosn 設計的初衷,此外可程式設計性,事件機制,擴充套件性,高吞吐量,都是設計中的重要考量因素。
SOFAMosn 核心能力
介紹完結構設計方面的一些思路,我們來看看 SOFAMosn 0.1.0 的核心能力。
在網路核心能力方面,我們將 IO 處理相關能力封裝抽象成可程式設計介面,這部分我們已經做過效能優化,可以單獨使用;SOFAMosn 提供了內建的 TCP 代理功能,也做過效能優化,可單獨使用;此外 SOFAMosn 支援 TLS 鏈路加密,目前複用了 Golang 的實現,後面的章節會介紹 Golang TLS 效能實驗。SOFAMosn 可以配合 iptables 透明轉發支援TProxy 模式。同時,MOSN 支援平滑 reload,平滑升級。
在多協議方面,0.1.0 版本中 SOFAMosn 重點支援 SOFARPC,並已運用在螞蟻生產環境中。同時 SOFAMosn 支援HTTP/1.1,HTTP/2.0 的基本功能,實現方式是使用開源的 HTTP/1.1實現 FastHTTP 和 Golang 自帶的 HTTP2 實現。由於 FastHTTP 和 HTTP2 都自帶了 IO,連結池等功能,所以這兩個協議的支援暫時是脫離 SOFAMosn 整體設計的,效能等方面也還沒有做優化,我們會在後續版本迭代考慮將其納入到 SOFAMosn 的框架體系,並進行效能優化。此外,我們正在研發 Dubbo,HSF 的支援,會在後續版本中推出。同時,目前已支援的 SOFARPC,HTTP/1.1,HTTP/2.0 都支援 Mes h間的 TLS 鏈路加密。
此處,在核心路由方面,0.1.0 版本 SOFAMosn 在核心功能上對齊 Envoy,支援 virtual host 匹配,支援 route match匹配,支援 subset 路由匹配/負載均衡。
在後端管理功能方面,支援基礎負載均衡演算法,支援主動健康檢查等必須功能。
除核心功能外,SOFAMosn 根據我們落地的一些經驗提供了一些亮點功能。
首先,SOFAMosn 支援 X-PROTOCOL,一種更輕量級的方式支援自定義 RPC 協議,對於無需解包的相對簡單的場景,將 RPC 資料作為 TCP 或者 HTTP/2.0 的payload 進行轉發,同時支援所有無需解包的路由負載策略。
同時我們計劃在 X-PROTOCOL 中加入編解碼擴充套件點,支援需要解包的場景。在平滑升級的支援上,除了經典的傳遞 listener fd+ 協議層等待方式,SOFAMosn 支援對存量連結進行協議無關的遷移。同時為了部署升級,SOFAMosn 支援指定 / 更新前後端通訊協議。
在 Istio 整合方案上,SOFAMosn 0.1.0 支援 Istio 0.8 版本 Pilot V0.4API 全動態配置執行,支援 xDS on ADS 核心功能,後續版本會不斷補齊功能。SOFAMosn 同時支援靜態配置模型執行。
除了能力支援,SOFAMosn 在網路層,協議處理層,基於 TCP 的私有協議層都提供了可擴充套件的能力,使得自定義業務可以優雅整合。在螞蟻落地的過程中我們內部的 SOFAMosn 依賴於開源版本,通過可擴充套件的方式來實現螞蟻內部的自有業務,在工程落地上提供了可行的方案。
效能
在介紹了核心功能以後,我們再看另一個大家非常關注的問題,效能,這也是目前關注度較高的問題之一。
在 SOFAMosn 0.1.0 版本,我們重點優化了基於 SOFAMosn 整體框架的協議在 Sidecar 模式下單核轉發的效能,即 TCP,SOFARPC 的單核轉發效能。
首先我們分享一下我們在單核場景下優化的一些手段和經驗。我們使用的方式主要是獨佔綁核,記憶體,IO,排程等方面進行優化。
首先看綁核,在指定 P=1 的情況下,獨佔綁核不論在系統呼叫執行效率,cache locality affinity 兩個方面都比更表現更好,整體吞吐量提升大約 30%。其次是記憶體優化,我們取樣了 SLAB-style 的回收機制來提高複用,減少記憶體 copy;
同時在記憶體分配上需要考慮 Golang 記憶體模型的親和性,儘量減少 arena 區記憶體申請;最後,大家都知道 Golang的 GC 需要是你要去熟悉並適應他的,很多細節需要關注,儘量減少GC scanobject的壓力。
在 IO 方案,Golang 的 IO 模型是同步化的,在讀方面既要儘可能多讀,又要避免頻繁呼叫 SetReadDeadline 造成的的影響,在我們壓測下面頻繁呼叫 SetReadDeadline 會對吞吐量有一定影響。在寫方面需要適度 buffer,例如由多 worker 協程驅動造成某個 IO 協程頻繁寫系統 IO 也會造成吞吐量下降。另一個需要注意的方面是,在多協程場景下需要避免讀寫頻率不均衡,這也是造成整體吞吐量下降的一個潛在原因。
另外,如果讀或寫大量觸發,會造成大量系統呼叫,這會引起 Golang runtime 排程成本升高。在 Golang runtime 排程方面,首先會觸發協程排程造成時間消耗,同時 runtime 排程本身沒有 OS 執行緒排程靈敏,也會有一定的時間損耗。同時 OS 系統呼叫本身也有會耗時,會造成效能下降。
這裡我分享一些我們在效能優化過程中遇到的真實的 case,除了 IO 方面的思考,還要關注一下排程均衡方面的問題。
首先我們利用協程池化來避免 runtime.morestack 的問題,其次在單核場景下需要重點關注 G 是否在飢餓狀態,造成資源浪費。
介紹完效能優化的一些過程,我們來看一下目前我們在效能優化上的一些結果,即單核 TCP 轉發的效能,和單核SOFARPC 轉發的效能。可以看到,在單核 TCP 轉發場景,SOFAMosn 0.1.0 版本和 Envoy 1.7版本轉發效能差距可控,後續版本我們會繼續優化。
此外,前面提到過 TLS 的實現,我們再來看一下效能方面的一些探索。首先介紹了一下測試的場景。在這個場景下,我們發現對於 ECDHE 演算法,Golang 原生的實現效能雖然低於Ningx(使用 OpenSSL),但是高於 Golang with boring SSL。通過對具體演算法和協議的效能壓測,程式碼調研我們得出如下結論。可以看出對於 ECDHE-P256加密套件,Golang 原生實現的效能是很不錯的,可以放心使用。
除了這些優化點以後,我們會在後續版本持續進行效能優化,多核優化,記憶體優化,同時利用使用者態,核心態的加速技術來提升 SOFAMosn 的轉發效能。在TLS加解密方面,我們將會嘗試基於本地加速卡和 Keyless 架構的 Offload 加速,這也是我們在螞蟻網路從中已經落地的一些技術手段。
RoadMap
最後我介紹一下SOFAMesh 的 RoadMap(時間為大體範圍,具體釋出請關注本公眾號):
8月第一週我們將釋出 SOFAMesh 0.1.0 版本,這個版本重點支援 Proxy 核心能力,支援 xDS V0.4 API 核心功能,支援 SOFARPC 等通訊協議。
8月底我們將釋出 0.2.0 版本,在不斷完善提升核心能力的基礎上,我們會完善 X-Protocol 的功能和擴充套件性,以支援私有 RPC 協議擴充套件;同時我們將支援 Dubbo/HSF 通訊協議,並接入基於 ZK 的服務註冊中心。同時我們將重點加強 HTTP/2.0 的功能,效能優化。我們還將支援 K8S operator,使得 SOFA Mesh 可以接入 K8S 資源。
除功能性補強以外,我們會持續優進行效能優化,重點在多核效能,整體記憶體優化。此外,我們會持續推進程式碼優化,完善測試等基礎性工作。
9月底我們將釋出 0.3.0,重點提供 Mixer 整合,提供 precondition,quota,report 功能。同時在9月提供熔斷和限流的能力。
目前SOFAMosn仍然是一個初級版本,我們將持續投入補充,改進,優化,也歡迎開源社群感興趣的朋友一起加入SOFAMesh開源版的建設。
補充
本文基於作者在 Service Mesh Meetup #2 分享的部分內容所整理,現場分享的 PPT 以及視訊,可以從 https://www.itdks.com/eventlist/detail/2455 觀看
長按關注,獲取最新分散式架構乾貨
歡迎大家共同打造 SOFAStack https://github.com/alipay