Go 語言版 Service Mesh Sidecar 剖析系列之 SOFAMosn 的誕生和特性總覽

ServiceMesher發表於2018-09-13

GitHub:github.com/alipay/sofa…

文件地址:www.sofastack.tech/sofa-mosn/d…

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

SOFA MOSN æ¶æå¾

簡單來說,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 之間的請求。

Go 語言版 Service Mesh Sidecar 剖析系列之 SOFAMosn 的誕生和特性總覽

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

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

  2. MOSN 上下游協議可配置為當前支援的協議中的任意一種

SOFAMosn 內部是如何完成代理功能的

瞭解 SOFAMosn 的代理能力,我們需要窺探它的實現框架以及資料在其內部的流轉。這裡我們先介紹組成 SOFAMosn 的模組,再介紹 SOFAMosn 的分層設計

SOFAMosn 的組成模組

Go 語言版 Service Mesh Sidecar 剖析系列之 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);出向與入向過程基本相反

Go 語言版 Service Mesh Sidecar 剖析系列之 SOFAMosn 的誕生和特性總覽

下面我們簡單介紹每一層的作用,關於每一層的特性,請參考:

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 傳送出去

Go 語言版 Service Mesh Sidecar 剖析系列之 SOFAMosn 的誕生和特性總覽

SOFAMosn 如何提高 Golang 的轉發效能

Golang 的轉發效能比起 C++ 是稍有遜色的,為了儘可能的提高 MOSN 的轉發效能,我們線上程模型上進行優化,當前 MOSN 支援兩種執行緒模型,使用者可根據場景選擇開啟適用的模型。

模型一

如下圖所示,模型一使用 Golang 預設的 epoll 機制,對每個連線分配獨立的讀寫協程進行阻塞讀寫操作, proxy 層做轉發時,使用常駐 worker 協程池負責處理 Stream Event


Go 語言版 Service Mesh Sidecar 剖析系列之 SOFAMosn 的誕生和特性總覽

  • 此模型在 IO上使用 Golang 的排程機制,適用於連線數較少的場景,例如:SOFAMosn 作為 sidecar、與 client 同機部署的場景

模型二

如下圖所示,模型二基於 NetPoll 重寫 epoll 機制,將 IO 和 PROXY 均進行池化,downstream connection將自身的讀寫事件註冊到netpoll的epoll/kqueue wait 協程,epoll/kqueue wait 協程接受可讀事件時,觸發回撥,從協程池中挑選一個執行讀操作

Go 語言版 Service Mesh Sidecar 剖析系列之 SOFAMosn 的誕生和特性總覽

  • 使用自定義 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 原始碼解析

相關連結:

SOFA 文件: www.sofastack.tech/

SOFA: github.com/alipay

SOFAMosn: github.com/alipay/sofa…

Go 語言版 Service Mesh Sidecar 剖析系列之 SOFAMosn 的誕生和特性總覽



相關文章