SOFAMesh中的多協議通用解決方案x-protocol介紹系列(3)——TCP協議擴充套件

螞蟻金服分散式架構發表於2018-12-18

2018年上半年,螞蟻金服決定基於 Istio 訂製自己的 ServiceMesh 解決方案,並在6月底正式對外公佈了 SOFAMesh。

在 SOFAMesh 的開發過程中,針對遇到的實際問題,我們給出了一套名為 x-protocol 的解決方案,本文將會對這個解決方案進行詳細的講解,本篇為最後一篇。

歷史文章:

SOFAMesh中的多協議通用解決方案x-protocol介紹系列(1) : DNS通用定址方案

SOFAMesh中的多協議通用解決方案x-protocol介紹系列(2):快速解碼轉發

SOFAMesh中的多協議通用解決方案x-protocol介紹系列(3)——TCP協議擴充套件

背景

在 Istio 和 Envoy 中,對通訊協議的支援,主要體現在 HTTP/1.1 和 HTTP/2 上,這兩個是 Istio/Envoy 中的一等公民。而基於 HTTP/1.1 的 REST 和基於 HTTP/2 的gRPC,一個是目前社群最主流的通訊協議,一個是未來的主流,Google 的寵兒,CNCF 御用的 RPC 方案,這兩個組成了目前 Istio 和 Envoy(乃至 CNCF 所有專案)的黃金組合。

而我們 SOFAMesh,在第一時間就遇到和 Istio/Envoy 不同的情況,我們需要支援REST 和 gRPC 之外的眾多協議:

  • SOFARPC:這是螞蟻金服大量使用的 RPC 協議(已開源)

  • HSF RPC:這是阿里集團內部大量使用的 RPC 協議(未開源)

  • Dubbo RPC: 這是社群廣泛使用的 RPC 協議(已開源)

  • 其他私有協議:在過去幾個月間,我們收到需求,期望在 SOFAMesh 上執行其他TCP 協議,部分是私有協議

為此,我們需要考慮在 SOFAMesh 和 SOFAMosn 中增加這些通訊協議的支援,尤其是要可以讓我們的客戶非常方便的擴充套件支援各種私有 TCP 協議:

SOFAMesh中的多協議通用解決方案x-protocol介紹系列(3)——TCP協議擴充套件

實現分析

我們來大體看一下,在 SOFAMesh/Istio 中要新增一個通訊協議需要有哪些工作:

SOFAMesh中的多協議通用解決方案x-protocol介紹系列(3)——TCP協議擴充套件

  1. protocol decoder:負責解析協議,讀取協議欄位

  2. protocol encoder:負責生成請求報文,注意通常會有改動,比如修改某些header

  3. 在pilot中需要為新協議生成 Virtual Host 等配置,有 inbound 和 outbound 兩份,分別下發到Sidecar

  4. 在Sidecar中,根據下發的 Virtual Host 等配置,進行請求匹配,以決定請求該轉發到何處

備註:實際下發的配置不止 Virtual Host 配置,為了簡單起見,我們僅以 Virtual Host 為例做講解。

其中,protocol encoder 和 protocol decoder 是容易理解的,對於新的通訊協議肯定需要有協議編解碼層面的工作必須要完成,這塊有工作量是很自然的。

我們來看看第三塊的工作量是什麼,inbound 和 outbound 的Virtual Host配置示例如下:

SOFAMesh中的多協議通用解決方案x-protocol介紹系列(3)——TCP協議擴充套件

outbound 配置中,注意 domains 欄位是各種域名和ClusterIP,而 routes 中,match是通過prefix來匹配。我們結合HTTP/1.1,domains欄位是用來和請求的Host header進行域名匹配的,比如 Host: istio-telemetry,這決定了哪些請求是要轉發到 istio-telemetry 這個服務的。routes的match用來進行路由匹配的,通過HTTP請求的path進行匹配。

SOFAMesh中的多協議通用解決方案x-protocol介紹系列(3)——TCP協議擴充套件

inbound 配置類似,只是inbound更簡單,domains 匹配*就可以。

從上面的例子中可以看到,Istio 和 Envoy 的設計有非常濃重的HTTP協議的味道,各種語義都是和 HTTP 直接相關。而當我們進行 TCP 協議的轉發時,就需要將請求的協議欄位進行對映,對映到 HTTP 的相應語義。

比如,最基本的 Destination,原始語義是請求的目的地,在前面的文章中我們指出過這是請求轉發最關鍵的欄位。在 HTTP 協議中,通常是通過 Host header 和 Path 表示,對於 REST 而言還有重要的 Method 欄位。

下面的格式是其他各種協議對這個 Destination 原始語義的實際實現方式:

協議 實現
原始語義 請求的目的地(Destination)
HTTP/1.1 Host header,Method,Path
HTTP/2 Header幀中的偽header :authority:path:method
Bolt協議 header map中key為”service”的欄位
HSF協議 協議頭中的服務介面名和服務方法名
Dubbo協議 data欄位(payload)中的path/method

這些通訊協議在下發規則和進行請求匹配時,就需要進行協調:

  • 定義好 Virtual Host 配置中的 domains 欄位和 route 中的 match 用到的欄位在當前通訊協議中的實際語義

  • 在 protocol encoder 中讀取請求的協議欄位,和上面的欄位對應

  • 然後進行請求路由規則匹配(參照 HTTP/1.1中的 domain 和 route match 的匹配)

而這些都是需要以程式碼的方式進行實現,以滿足新通訊協議的要求。正規的做法,是每次新增一個通訊協議就將上述的工作內容重複一遍。這會直接導致大量的高度類似的重複程式碼。

x-protocol的實現

在上述需要在協議擴充套件時修改的四個內容中,有一塊是特別的:生成 Virtual Host 配置的工作是在 Pilot 中實現的,而其他三個是在 Sidecar ( Envoy 或 MOSN )中。考慮到 protocol encoder 和 protocol decoder 的工作是必不可少的,必然會修改Sidecar來增加實現程式碼,因此簡化開發的第一個想法就是:能不能做到不修改Pilot?

基本思路就是固定好原始語義,避免每個通訊協議都對映一遍。從前面我們列出來的各個協議的對映情況看,對於RPC協議而言,一般目的地資訊都是服務名(有些是介面名)+方法名居多,因此可以考慮直接將服務名和方法名固定下來:

  • RPC協議在 Virtual Host 配置中就固定為服務名對應 domains 欄位,方法名對應 route 中的 match 用到的欄位,這樣只要修改一次然後各個 RPC 協議公用此配置,以後就不用再重複修改 Pilot。

  • protocol encoder 在解析通訊協議完成之後,就直接將協議中對應服務名和方法名的欄位提取出來,後面的匹配處理過程就可以公用一套通用實現,這樣路由匹配這塊也可以不用在重複開發。

因此,在x-protocol中,如果需要引入一個新的通訊協議,需要的工作內容只有必不可少的 protocol encoder 和 protocol decoder,和實現以下幾個介面:

SOFAMesh中的多協議通用解決方案x-protocol介紹系列(3)——TCP協議擴充套件

總結

X-protocol 在支援新通訊協議上的做法並無新奇之處,只是由於需求特殊有眾多通訊協議需要支援,在開發時發現大量重複工作,因此我們選擇了一條可以讓後面更舒服一點的道路。

目前這個方案在 SOFAMesh 中採用,我們將進一步檢驗實際效果,也會和合作的小夥伴時驗證,看他們在自行擴充套件新協議時是否足夠理想。這個方案理論上應該可以同樣適用於 Istio、Envoy 體系,隨著社群對Istio的接受程度的提高,在 Istio 上支援各種TCP 通訊協議的需求會越來越多,有理由相信Istio後續可能也會出現類似的方案。畢竟,每次都改一大堆類似的東西,不是一個好做法。

相關連結:

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

SOFA: https://github.com/alipay

SOFAMosn:

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

SOFAMesh:

https://github.com/alipay/sofa-mesh

推薦閱讀

螞蟻金服SOFAMesh在多語言上的實踐 | CNUTCon 實錄

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

螞蟻金服Service Mesh新型網路代理的思考與實踐 | GIAC 分享實錄

SOFAMesh中的多協議通用解決方案x-protocol介紹系列(3)——TCP協議擴充套件

長按關注,獲取分散式架構乾貨

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

來源:https://juejin.im/post/5c188e4c6fb9a049a81f3f5d

相關文章