歡迎光臨
每天分享高質量文章

【剖析 | SOFAMosn】系列之 SOFAMosn 的誕生和特性總覽

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 你將在如下幾個方面獲得收益:

  1. SOFAMosn 使用 Golang 作為開發語言,開發效率高,在雲原生時代可與 k8s 等技術無縫對接,有利於加速微服務的落地;

  2. SOFAMosn 可代理 Java,C++,Golang,PHP,Python 等異構語言之間組件的互相呼叫,避免多語言版本組件的重覆開發,可提高業務開發效率,目前 SOFAMosn 已經在螞蟻金服中作為跨語言 RPC 呼叫的橋梁被使用;

  3. SOFAMosn 可提供靈活的流量調度能力,有助於運維體系的支撐,包括:藍綠升級、容災切換等;

  4. 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 之間的請求。

這裡有一些需要註意的是:

  1. 你可以使用 MOSN 只代理 Client 的請求,MOSN 可以直接訪問 Server,鏈路:Client -> MOSN -> Server,反之亦然

  2. 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 用來對後端做流控,為開發中模塊

  • LabAdmin 模塊為實驗性待開發模塊

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 層提供路由選擇,負載均衡等的能力,做資料流之間的轉發;

下麵是將此圖打開後的示意圖

  1. MOSN 在 IO 層讀取資料,通過 read filter 將資料發送到 Protocol 層進行 Decode

  2. Decode 出來的資料,根據不同的協議,回呼到 stream 層,進行 stream 的創建和封裝

  3. stream 創建完畢後,會回呼到 Proxy 層做路由和轉發,Proxy 層會關聯上下游間的轉發關係

  4. Proxy 挑選到後端後,會根據後端使用的協議,將資料發送到對應協議的 Protocol 層,對資料重新做 Encode

  5. 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 支持

  • 【待領取】協議處理及多協議擴展機制

  • 【待領取】跨協議轉發引擎機制實現原理剖析

  • 【待領取】後端鏈接管理,健康檢查

  • 【待領取】負載均衡原理剖析

  • 【待領取】路由支持及擴展機制剖析

  • 【待領取】網絡層,協議層擴展點

  • 【待領取】無損重啟/升級

  • 【待領取】記憶體復用剖析

領取方式:

直接回覆本公眾號想認領的文章名稱,我們將會主動聯繫你,確認資質後,即可加入Lab/>,It’s your show time!


相關鏈接:

SOFA 文件: http://www.sofastack.tech/

SOFA: https://github.com/alipay

SOFAMosn: https://github.com/alipay/sofa-mosn

延伸閱讀:

大規模微服務架構下的 Service Mesh 探索之路

開源 | Service Mesh 資料平面 SOFAMosn 深層揭秘

開源 | SOFAMesh 的通用協議擴展


長按關註,獲取分佈式架構乾貨

歡迎大家共同打造 SOFAStack https://github.com/alipay

赞(0)

分享創造快樂