SOFA
Scalable Open Financial Architecture
是螞蟻金服自主研發的金融級分佈式中間件,包含了構建金融級雲原生架構所需的各個組件,是在金融場景里錘煉出來的最佳實踐。
本文為《剖析 | SOFAMosn》第一篇。
《剖析 | SOFAMosn》系列由 SOFA 團隊和原始碼愛好者們出品,
專案代號:
,今天開啟共建招募,加入方式見底部。
SOFAMosn 的誕生
雲原生時代,Service Mesh 作為一個專用的基礎設施層,用於提供安全、快速、可靠、智慧的服務間通訊,可為微服務的連接、管理和監控帶來巨大的便利,從而加速微服務的落地。
作為國內領先的金融服務提供商,螞蟻金服對系統架構的性能、穩定性、安全性要求極高,且面對的運維架構複雜。為了達到高可用和快速迭代的目的,螞蟻金服正全面擁抱微服務,雲原生, 故 Service Mesh 成為助力螞蟻 SOFA5,以及兼容 K8S 的容器平臺 Sigma等微服務化關鍵組件落地的重要推手。
在 Service Mesh 落地的方案挑選中, Istio 作為 Service Mesh 的集大成者,無論在功能實現,穩定性,擴展性,以及社區關註度等方面都是不二選擇,其資料平面 Envoy 更是具有優秀的設計,可擴展的 XDS API,以及較高的性能等特點,螞蟻一開始便將 Istio 作為重點的關註物件。
然而,由於 Envoy 使用 C++ 語言開發,不符合螞蟻技術棧的發展方向且無法兼容現在的運維體系,以及螞蟻內部有許多業務定製化的訴求,導致我們無法直接使用 Istio。經過調研發現,作為雲計算時代主流語言的 Golang 同樣具有較高的轉發性能,這促使我們考慮開發 Golang 版本高性能的 sidecar 來替換 Envoy 與 Istio 做集成。
今天,我們就來介紹它:“SOFAMosn” 。
初識 SOFAMosn
簡單來說,SOFAMosn 是一款採用 Golang 開發的 Service Mesh 資料平面代理,由螞蟻金服系統部網絡團隊、螞蟻金服中間件團隊、UC 大文娛團隊共同開發,功能和定位類似 Envoy,旨在提供分佈式,模塊化,可觀察,智慧化的代理能力。它通過模塊化,分層解耦的設計,提供了可編程,事件機制,擴展性,高吞吐量的能力。
當前, SOFAMosn 已支持 Envoy 和 Istio 的 API,實現並驗證了 Envoy 的常用功能(全量功能在開發中),通過 XDS API 與 Pilot 對接,SOFAMosn 可獲取控制面推送的配置信息,來完成代理的功能。在實踐中,你可以使用 SOFAMosn 替代 Envoy 作為轉發平面與 Istio 集成來實現 Service Mesh 組件,也可以單獨使用 SOFAMosn 作為業務網關,通過使用 SOFAMosn 你將在如下幾個方面獲得收益:
-
SOFAMosn 使用 Golang 作為開發語言,開發效率高,在雲原生時代可與 k8s 等技術無縫對接,有利於加速微服務的落地;
-
SOFAMosn 可代理 Java,C++,Golang,PHP,Python 等異構語言之間組件的互相呼叫,避免多語言版本組件的重覆開發,可提高業務開發效率,目前 SOFAMosn 已經在螞蟻金服中作為跨語言 RPC 呼叫的橋梁被使用;
-
SOFAMosn 可提供靈活的流量調度能力,有助於運維體系的支撐,包括:藍綠升級、容災切換等;
-
SOFAMosn 提供TLS、服務鑒權等能力,可滿足服務加密與安全的訴求;
當前 SOFAMosn 已經在 Github 上開源,我們歡迎所有感興趣的同學參與進來,與我們一起共建一個精品的 Golang Sidecar,專案地址為:https://github.com/alipay/sofa-mosn
為了幫助大家更好的理解 SOFAMosn,本文作為開篇文章,會整體性的介紹 SOFAMosn 的特性以期給大家一個完整的印象,具體的細節這裡不做展開,如果您對細節感興趣,歡迎關註後續文章。
本文介紹的內容將包括 :
-
SOFAMosn 是如何工作的
-
SOFAMosn 內部是如何完成代理功能的
-
SOFAMosn 如何提高Golang的轉發性能
-
SOFAMosn 做了哪些記憶體優化
-
SOFAMosn 如何做到系統的高可用
-
SOFAMosn 如何支持擴展
-
SOFAMosn 如何做到安全
SOFAMosn 是如何工作的
SOFAMosn 本質是一個 4-7 層代理,所以它可以以獨立行程的形式作為 sidecar 與用戶程式部署在相同的物理機或者VM中,當然也可以以獨立網關的形式單獨運行在一臺主機或者虛擬機中。
以下圖為例,MOSN (註: SOFAMosn 有時也簡稱為 MOSN) 與 Service 部署在同一個 Pod 上,MOSN 監聽在固定的端口,一個正向的請求鏈路包括如下步驟:
-
ServiceA 作為客戶端可使用任意語言實現,可使用目前支持的任意的協議型別,比如HTTP1.x,HTTP2.0,SOFARPC 等,將 sub/pub、request 信息等發送給MOSN
-
MOSN 可代理 ServiceA 的服務發現,路由,負載均衡等能力,通過協議轉換,轉發 ServiceA 的請求信息到上游的 MOSN
-
上游 MOSN 將接收到的請求通過協議轉換,發送到代理的 ServiceB 上
反向鏈路類似,通過上述的代理流程,MOSN 代理了 Service A 與 Service B 之間的請求。
這裡有一些需要註意的是:
-
你可以使用 MOSN 只代理 Client 的請求,MOSN 可以直接訪問 Server,鏈路:Client -> MOSN -> Server,反之亦然
-
MOSN 上下游協議可配置為當前支持的協議中的任意一種
SOFAMosn 內部是如何完成代理功能的
瞭解 SOFAMosn 的代理能力,我們需要窺探它的實現框架以及資料在其內部的流轉。這裡我們先介紹組成 SOFAMosn 的模塊,再介紹 SOFAMosn 的分層設計
SOFAMosn 的組成模塊
在上圖中,藍色框中的模塊為當前已經支持的模塊,紅色虛線模塊為開發中模塊,其中:
-
Starter
用於啟動 MOSN,包括從配置檔案或者以 XDS 樣式啟動,其中Config
用於配置檔案的解析等,XDS
用於和 Istio 交互,獲取 Pilot 推送的配置等 -
MOSN 解析配置後,會生成
Server
以及Listener
,在 Listener 中有監聽端口、 ProxyFilter 、Log 等信息;Server 包含 Listener ,為 MOSN 運行時的抽象,Server 運行後,會開啟 Listener 監聽,接受連接等 -
MOSN 運行起來後,還會生成
Upstream
相關信息,用於維護後端的 Cluster和 Host信息 -
MOSN 在轉發請求時,會在 Upstream 的 Cluster 中通過
Router
以及LoadBalancer
挑選 Host -
Router
為 MOSN 的路由模塊,當前支持根據 label 做路由等 -
LoadBalance
為 MOSN 的負載均衡模塊,支持 WRR,Subset LB -
Metrics
模塊用於對協議層的資料做記錄和追蹤 -
Hardware
為 MOSN 後期規劃的包括使用加速卡來做 TLS 加速以及 DPDK 來做協議棧加速的一些硬體技術手段 -
Mixer
用於對請求做服務鑒權等,為開發中模塊 -
FlowControl
用來對後端做流控,為開發中模塊 -
Lab
和Admin
模塊為實驗性待開發模塊
SOFAMosn 的分層設計
為了轉發資料,實現一個4-7層的 proxy,在分層上,SOFAMosn 將整體功能分為 “網絡 IO 層”,”二進制協議處理層”,”協議流程處理層”以及”轉發路由處理層” 等四層進行設計,每一層實現的功能高度內聚可用於完成獨立的功能,且層與層之間可相互配合實現完整的 proxy 轉發。
如下圖所示:SOFAMosn 對請求做代理的時候,在入口方向,會依次經過網絡 IO 層(NET/IO),二進制協議處理層(Protocol),協議流程處理層(Streaming),轉發路由處理層(Proxy);出向與入向過程基本相反
下麵我們簡單介紹每一層的作用,關於每一層的特性,請參考:
https://github.com/alipay/sofa-mosn/blob/master/docs/design/MOSNLayerFeature.md
-
NET/IO 層提供了 IO 讀寫的封裝以及可擴展的 IO 事件訂閱機制;
-
Protocol 層提供了根據不同協議對資料進行序列化/反序列化的處理能力;
-
Streaming 層提供向上的協議一致性,負責 stream 的生命周期,管理 Client / Server 樣式的請求流行為,對 Client 端stream 提供池化機制等;
-
Proxy 層提供路由選擇,負載均衡等的能力,做資料流之間的轉發;
下麵是將此圖打開後的示意圖
-
MOSN 在 IO 層讀取資料,通過 read filter 將資料發送到 Protocol 層進行 Decode
-
Decode 出來的資料,根據不同的協議,回呼到 stream 層,進行 stream 的創建和封裝
-
stream 創建完畢後,會回呼到 Proxy 層做路由和轉發,Proxy 層會關聯上下游間的轉發關係
-
Proxy 挑選到後端後,會根據後端使用的協議,將資料發送到對應協議的 Protocol 層,對資料重新做 Encode
-
Encode 後的資料會發經過 write filter 並最終使用 IO 的 write 發送出去
SOFAMosn 如何提高 Golang 的轉發性能
Golang 的轉發性能比起 C++ 是稍有遜色的,為了盡可能的提高 MOSN 的轉發性能,我們在執行緒模型上進行優化,當前 MOSN 支持兩種執行緒模型,用戶可根據場景選擇開啟適用的模型。
模型一
如下圖所示,模型一使用 Golang 預設的 epoll 機制,對每個連接分配獨立的讀寫協程進行阻塞讀寫操作, proxy 層做轉發時,使用常駐 worker 協程池負責處理 Stream Event
-
此模型在 IO上使用 Golang 的調度機制,適用於連接數較少的場景,例如:SOFAMosn 作為 sidecar、與 client 同機部署的場景
模型二
如下圖所示,模型二基於 NetPoll 重寫 epoll 機制,將 IO 和 PROXY 均進行池化,downstream connection將自身的讀寫事件註冊到netpoll的epoll/kqueue wait 協程,epoll/kqueue wait 協程接受可讀事件時,觸發回呼,從協程池中挑選一個執行讀操作
-
使用自定義 Netpoll IO 池化操作帶來的好處是:
-
當可讀事件觸發時,從協程池中獲取一個 goroutine 來執行讀處理,而不是新分配一個 goroutine,以此來控制高併發下的協程數量
-
當收到鏈接可讀事件時,才真正為其分配 read buffer 以及相應的執行協程。這樣可以優化大量空閑鏈接場景導致的額外協程和 read buffer 開銷
-
此模型適用於連接數較多,可讀的連接數有限,例如:SOFAMosn 作為 api Gateway 的場景
SOFAMosn 做了哪些記憶體優化
Golang 相比於 C++,在記憶體使用效率上依賴於 GC,為了提高 Golang 的記憶體使用率,MOSN 做瞭如下的嘗試來減少記憶體的使用,優化 GC 的效率:
-
通過自定義的記憶體復用接口實現了通用的記憶體復用框架,可實現自定義記憶體的復用
-
通過優化 []byte 的獲取和回收,進一步優化全域性記憶體的使用;
-
通過優化 socket 的讀寫迴圈以及事件觸發機制,減小空閑連接對記憶體分配的使用,進一步減少記憶體使用;
-
使用 writev 替代 write, 減少記憶體分配和拷貝,減少鎖力度;
SOFAMosn 如何做到系統的高可用
-
MOSN 在運行時,會開啟 crontab 進行監控,在程式掛掉時,會及時拉起;
-
同時,MOSN 在 進行升級或者 reload 等場景下做連接遷移時, 除了經典的傳遞 listener fd 加協議層等待方式以外,還支持對存量鏈接進行協議無關的遷移來實現平滑升級,平滑 reload 等功能;
-
在對存量連接進行遷移時,mosn 通過 forkexec 生成New mosn,之後依次對存量的請求資料做遷移,對殘留響應做遷移來完成;
SOFAMosn 如何支持擴展
MOSN 當前支持 “協議擴展” 來做到對多協議的支持,支持 “NetworkFilter 擴展” 來實現自定義 proxy 的功能,支持 “StreamFilter 擴展” 來對資料做過濾:
1. 協議擴展
MOSN 通過使用同一的編解碼引擎以及編/解碼器核心接口,提供協議的 plugin 機制,包括支持
-
SOFARPC
-
HTTP1.x, HTTP2.0
-
Dubbo
等協議,後面還會支持更多的協議
2. NetworkFilter 擴展
MOSN 通過提供 Network Filter 註冊機制以及統一的 packet read/write filter 接口,實現了Network Filter 擴展機制,當前支持:
-
TCP Proxy
-
Layer-7 Proxy
-
Fault Injection
3. StreamFilter 擴展
MOSN 通過提供 Stream Filter 註冊機制以及統一的 stream send/receive filter 接口,實現了 Stream Filter 擴展機制,包括支持:
-
支持配置健康檢查等
-
支持故障註入功能
SOFAMosn 如何做到安全
SOFAMosn 中,通過使用 TLS 加密傳輸和服務鑒權來保證訊息的安全可靠,在未來還會通過使用 keyless 等方案來提高加解密的性能,下麵我們介紹SOFAMosn 在 TLS 上的一些實踐
1. TLS 選型
-
在 SOFAMosn 中使用 TLS 有兩種選擇,1) 使用 Golang 原生的 TLS , 2) 使用 cgo 呼叫 Boring SSL
-
我們通過壓測發現,在 ECDHE-ECDSA-AES256-GCM-SHA384 這種常用的加密套件下,Go 自身的 TLS 在性能上優於 Boring SSL,與 Openssl 相差不多
-
經過調研發現,Go 對 p256,AES-GCM 對稱加密,SHA,MD5 等演算法上均有彙編優化,因而我們選擇使用 Golang 自帶的 TLS 來做 SOFAMosn 的 TLS 通信
2. TLS 方案
-
SOFAMosn 間使用 Golang 原生的 TLS 加密,支持 listener 級別的 TLS 配置,配置包括證書鏈與證書串列等,用來做監聽時使用;支持 cluster 級別的 TLS 配置,cluster 配置對所有的 host 生效,用來向後端發起連接時使用;host 中有一個配置用來標明自己是否支持 TLS
-
SOFAMosn server 通過使用 Listener 的 Inspector 功能,可同時處理客戶端的 TLS 和 非 TLS 請求
-
SOFAMosn client 在發起連接的時候,根據挑選的 host 是否支持 TLS 來決定是否使用 TLS 發起連接
歡迎加入 ,參與 SOFAMosn 原始碼解析
-
【剖析 | SOFARPC 框架】系列已經完成領取,SOFA 團隊正在與愛好者們打磨內容;
-
【剖析 | SOFABolt】已被認領兩篇,持續開放認領中;
今天我們很開心的推出
本文作為《剖析 | SOFAMosn》系列的開場篇,主要還是希望大家對 SOFAMosn 設計的背景和功能等有一個整體的認識和瞭解,之後,我們會逐步詳細介紹每部分的代碼設計和實現,預計會按照如下的目錄進行:
-
【待領取】使用 SOFAMosn 搭建 Service Mesh 平臺
-
【待領取】配置檔案解析與API模型
-
【待領取】Istio 對接
-
【待領取】網絡通信與 IO 處理
-
【待領取】TLS 支持
-
【待領取】協議處理及多協議擴展機制
-
【待領取】跨協議轉發引擎機制實現原理剖析
-
【待領取】後端鏈接管理,健康檢查
-
【待領取】負載均衡原理剖析
-
【待領取】路由支持及擴展機制剖析
-
【待領取】網絡層,協議層擴展點
-
【待領取】無損重啟/升級
-
【待領取】記憶體復用剖析
領取方式:
直接回覆本公眾號想認領的文章名稱,我們將會主動聯繫你,確認資質後,即可加入
相關鏈接:
SOFA 文件: http://www.sofastack.tech/
SOFA: https://github.com/alipay
SOFAMosn: https://github.com/alipay/sofa-mosn
延伸閱讀:
開源 | Service Mesh 資料平面 SOFAMosn 深層揭秘
開源 | SOFAMesh 的通用協議擴展
長按關註,獲取分佈式架構乾貨
歡迎大家共同打造 SOFAStack https://github.com/alipay