Categories
程式開發

Servicemesh和API Gateway關係深度探討


前言

關於Service Mesh和API Gateway之間的關係,這個問題過去兩年間經常被問起,社區也有不少文章和資料給出解答。其中不乏 Christian Posta 這樣的網紅給出過深度介紹。我在這裡做一個資料的整理和匯總,結合個人的理解給出一些看法。另外在本文最後,介紹螞蟻金服在Service Mesh和API Gateway融合的這個最新領域的一些開創性的實踐和探索,希望給大家一個更有體感的認知。

備註1:為了節約篇幅,我們將直奔主題,假定讀者對Servicemesh和API Gateway已有基本的了解。
備註2: 這邊文章更關注於梳理整個脈絡,內容不會展開的特別細,尤其是其他文章已經詳細闡述的部分。如果您在瀏覽本文之後,還想更深入的了解細節,請繼續閱讀文章最後的參考資料和推薦閱讀。

原本清晰的界限:定位和職責

首先,Service Mesh和API Gateway在功能定位和承擔的職責上有非常清晰的界限:

  • Service Mesh:微服務的網絡通信基礎設施,負責(系統內部的)服務間的通訊
  • API Gateway: 負責將服務以API的形式暴露(給系統外部),以實現業務功能

如上圖所示:

https://static001.infoq.cn/resource/image/0a/73/0af8dd3b654d32a7913d76224d582b73.png

從功能和職責上說:

  • 位於最底層的是拆分好的原子微服務,以服務的形式提供各種能力
  • 在原子微服務上是(可選的)組合服務,某些場景下需要將若干微服務的能力組合起來形成新的服務
  • 原子微服務和組合服務部署於 系統內部,在採用servicemesh的情況下,由servicemesh提供服務間通訊的能力
  • API Gateway用於將系統內部的這些服務暴露給 系統外部,以API的形式接受外部請求。

從部署上說:

  • Servicemesh部署在系統內部:因為原子微服務和組合服務通常不會直接暴露給外部系統
  • API Gateway部署在系統的邊緣:一方面暴露在系統之外,對外提供API供外部系統訪問;一方面部署在系統內部,以訪問內部的各種服務。

在這裡引入兩個使用非常廣泛的術語:

https://static001.infoq.cn/resource/image/0a/73/0af8dd3b654d32a7913d76224d582b73.png

  • 東西向通訊:指服務間的相互訪問,其通訊流量在服務間流轉,流量都位於系統內部
  • 南北向通訊:指服務對外部提供訪問,通常是通過API Gateway提供的API對外部保羅,其通訊流量是從系統外部進入系統內部。

解釋一下“東西南北”的由來:如上圖所示,通常在地圖上習慣性的遵循“上北下南,左東右西”的原則。

總結:Service Mesh和API Gateway在功能和職責上分工明確,界限清晰。但如果事情就這麼結束,也就不會出現Service Mesh和API Gateway關係的討論了,自然也不會有本文。

問題的根源在哪裡?

強烈推薦閱讀:附錄中 Christian Posta 的文章 “Do I Need an API Gateway if I Use a Service Mesh?”對此有深度分析和講解。

哲學問題:網關訪問內部服務,算東西向還是南北向?

如下圖所示,圖中黃色的線條表示的是API Gateway訪問內部服務:

https://static001.infoq.cn/resource/image/0a/73/0af8dd3b654d32a7913d76224d582b73.png

問題來了,從流量走向看:這是外部流量進入系統後,開始訪問對外暴露的服務,應該屬於“南北向”通訊,典型如上圖的畫法。但從另外一個角度,如果我們將API Gateway 邏輯上拆分為兩個部分,先忽略對外暴露的部分,單獨只看API Gateway 訪問內部服務的部分,這時可以視API Gateway 為一個普通的客戶端服務,它和內部服務的通訊更像是“東西向”通訊:

https://static001.infoq.cn/resource/image/0a/73/0af8dd3b654d32a7913d76224d582b73.png

所以,API Gateway 作為一個客戶端訪問內部服務時,到底算南北向還是東西向,就成為一個哲學問題:完全取決於我們如何看待API Gateway ,是作為一個整體,還是邏輯上分拆為對內對外兩個部分。

這個哲學問題並非無厘頭,在 API Gateway 的各種產品中,關於如何實現 “API Gateway 作為一個客戶端訪問內部服務” ,就通常分成兩個流派:

  1. 涇渭分明:視 API Gateway 和內部服務為兩個獨立事物,API Gateway訪問內部服務的通訊機制自行實現,獨立於服務間通訊的機制
  2. 兼容並濟:視 API Gateway 為一個普通的內部服務的客戶端,重用其內部服務間通訊的機制。

而最終決策通常也和產品的定位有關:如果希望維持API Gateway 的獨立產品定位,希望可以在不同的服務間通訊方案下都可以使用,則通常選擇前者,典型如kong;如果和服務間通訊方案有非常深的淵源,則通常選擇後者,典型如springcloud生態下的zuul和springcloud gateway。

但無論選擇哪個流派,都改變不了一個事實,當“API Gateway 作為一個客戶端訪問內部服務” 時,它的確和一個普通內部服務作為客戶端去訪問其他服務沒有本質差異:服務發現,負載均衡,流量路由,熔斷,限流,服務降級,故障注入,日誌,監控,鏈路追踪,訪問控制,加密,身份認證… 當我們把網關訪問內部服務的功能一一列出來時,發現幾乎所有的這些功能都是和服務間調用重複。

這也就造成了一個普遍現象:如果已有一個成熟的服務間通訊框架,再去考慮實現API Gateway,重用這些重複的能力就成為自然而然的選擇。典型如前面提到的 springcloud 生態下的 zuul 以及後面開發的 springcloud gateway,就是以重用類庫的方式實現了這些能力的重用。

這裡又是一個類似的哲學問題:當“API Gateway 作為一個客戶端訪問內部服務” 時,它以重用類庫的方式實現了代碼級別的能力重用,相當於自行實現了一個和普通服務間通訊方案完全一樣的客戶端,那這個“客戶端”發出來的流量算東西向還是南北向?

答案不重要。

Sidecar:真正的重合點

在進入servicemesh時代之後,Servicemesh和API gateway 的關係開始是這樣:

  1. 功能和職責清晰劃分
  2. 客戶端訪問服務的功能高度重疊

此時兩者的關係很清晰,而且由於當時Servicemesh和API Gateway是不同的產品,兩者的重合點只是在功能上。

而隨著時間的推移,當 Servicemesh 產品和 API Gateway 產品開始出現相互滲透時,兩者的關係就開始變得曖昧。

在Servicemesh出現之後,如何為基於Servicemesh的服務選擇合適的API Gateway方案,就慢慢開始提上日程,而其中選擇重用Servicemesh的能力也自然成為一個探索的方向,並逐步出現新式API Gateway產品,其想法很直接:

如何融合東西向和南北向的通訊方案?

其中的一個做法就是基於Servicemesh的Sidecar來實現API Gateway,從而在南北向通訊中引入Servicemesh這種東西向通訊的方案。這裡我們不展開細節,我這裡援引一個圖片(鳴謝趙化冰同學)來解釋這個方案的思路:

https://static001.infoq.cn/resource/image/0a/73/0af8dd3b654d32a7913d76224d582b73.png

這個時候servicemesh和API Gateway的關係就變得有意思了,因為servicemesh中sidecar的引入,所以前面的“哲學問題”又有了一個新的解法:API Gateway這次真的可以分拆為兩個獨立部署的物理實體,而不是邏輯上的兩個部分:

  1. API Gateway本體:實現API Gateway除了訪問內部服務之外的功能

  2. Sidecar:按照servicemesh的標準做法, 我們視API Gateway為一個部署於servicemesh中的普通服務,為這個服務1:1的部署sidecar

https://static001.infoq.cn/resource/image/0a/73/0af8dd3b654d32a7913d76224d582b73.png

在這個方案中,原來用於servicemesh的sidecar,被用在了API Gateway中,替代了API Gateway中原有的客戶端訪問的各種功能。這個方案讓API Gateway的實現簡化了很多,也實現了東西向和南北向通訊能力的重用和融合,而 API Gateway可以更專注於 “API Management” 的核心功能。

此時 servicemesh 和 API Gateway 的關係就從“涇渭分明”變成了“兼容並濟”。

而採用這個方案的公司,通常都是先有servicemesh產品,再基於servicemesh產品規劃(或者重新規劃)API Gateway方案,典型如螞蟻金服的SOFA Gateway產品是基於MOSN,而社區開源產品Ambassador和Gloo都是基於Envoy。

上述方案的優勢在於API Gateway和Sidecar獨立部署,職責明確,架構清晰。但是,和servicemesh使用sidecar被質疑多一跳會造成性能開銷影響效率一樣,API Gateway使用Sidecar也被同樣的質疑:多了一跳…

解決“多一跳”問題的方法簡單而粗暴,基於sidecar,將API Gateway的功能加進來。這樣API Gateway本體和Sidecar再次合二為一:

https://static001.infoq.cn/resource/image/0a/73/0af8dd3b654d32a7913d76224d582b73.png

至於走到這一步之後,Servicemesh和API Gateway是什麼關係:這到底算是Servicemesh/sidecar融合了API Gateway,還是API Gateway融合了Servicemesh/Sidecar?這個問題就像斑馬到底是白底黑紋還是黑底白紋一樣,見仁見智。

BFF:把融合進行到底

BFF(Backend For Frontend)的引入會讓Servicemesh和API Gateway走到一個更加親密的地步。

先來看看常規的BFF的玩法:

https://static001.infoq.cn/resource/image/0a/73/0af8dd3b654d32a7913d76224d582b73.png

在這裡,多增加了一個 BFF 層,介於API Gateway和內部服務(包括組合服務和原子微服務)之間。注意BFF的工作模式和組合服務很類似,都是組合多個服務。但差別在於:

  1. 組合服務還屬於服務的範疇,只是實現機制上組合了多個服務,對外暴露的依然是一個完整和規範的服務
  2. BFF不同,BFF如名字所示,Backend For Frontend,完全是為了前端而存在,核心目標之一是簡化前端的訪問
  3. 對我們今天的話題而言,最關鍵的一點:BFF完全收口了從外部進入的流量,而組合服務沒有,API Gateway是可以直接訪問原子微服務的

“BFF完全收口外部流量”,這一點在API Gateway和Sidecar融合之後,會變得很有想像空間,我們先看按照前面的融合方式,在有BFF的情況下,API Gateway和Sidecar融合後的情景:

https://static001.infoq.cn/resource/image/0a/73/0af8dd3b654d32a7913d76224d582b73.png

放大一點,單獨看API Gateway和BFF:

https://static001.infoq.cn/resource/image/0a/73/0af8dd3b654d32a7913d76224d582b73.png

注意到,流量從被API Gateway接收,到進入BFF在這個流程中,這個請求路徑中有兩個sidecar:

  1. 和BFF部署在一起的,是沒有API Gateway功能的普通Sidecar
  2. API Gateway和Sidecar融合之後,這就是一個“有API Gateway功能的大Sidecar”(或者是“有Sidecar功能的特殊API Gateway”):雖然扮演了API Gateway的角色,但本質上依然包含一個完整功能的sidecar,和BFF自帶的Sidecar是等同的

所以,問題來了:為什麼要放兩個sidecar在流程中,縮減到一個會怎麼樣?我們嘗試將兩個Sidecar合二為一,去掉BFF自帶的Sidecar,直接把扮演API Gateway的sidecar給BFF用:

https://static001.infoq.cn/resource/image/0a/73/0af8dd3b654d32a7913d76224d582b73.png

此時的場景是這樣:

  1. 流量直接打到BFF上(BFF前面可能會掛其他的網絡組件提供負載均衡等功能)
  2. BFF的sidecar接收流量,完成API Gateway的功能,然後將流量轉給BFF
  3. BFF通過sidecar調用內部服務(和沒有合併時一致)

https://static001.infoq.cn/resource/image/0a/73/0af8dd3b654d32a7913d76224d582b73.png

注意這裡有一個關鍵點,在前面時特意註明的:“BFF完全收口外部流量”。這是前提條件,因為原有的API Gateway集群已經不再存在,如果BFF沒能收口全部流量,則這些未能收口的流量會找不到API Gateway。當然,如果願意稍微麻煩一點,在部署時清晰的劃定需要暴露給外界的服務,直接在這些服務上部署帶API Gateway功能的Sidecar,也是可行的,只是管理上會比BFF模式要復雜一些。

另外,在部署上,按照上面的方案,我們會發現:API Gateway“消失”了—— 不再有一個明確物理部署的API Gateway的集群,常規的中心化的網關在這個方案中被融合到每一個BFF的實例中,從而實現另外一個重要特性:去中心化。

上述Servicemesh 和 API Gateway融合的方案,並未停留在紙面上。

在螞蟻金服內部,我們基於Servicemesh 和 API Gateway融合 + 去中心化的思路,進行過開創性的實踐和探索。以支付寶移動網關為例,在過去十年間,網關經歷了從單體到微服務,從中心化到去中心化,從共享的gateway.jar 包到利用MOSN實現網關Mesh化/Sidecar化,最終演變成了這樣一個方案:

https://static001.infoq.cn/resource/image/0a/73/0af8dd3b654d32a7913d76224d582b73.png

強烈推薦閱讀:附錄中我的同事 賈島 的文章 “螞蟻金服 API Gateway Mesh 思考與實踐” 對此有深入介紹和詳細描述。

總結

本文總結了Servicemesh 和API Gateway 的關係,整體上說兩者的定位和職責“涇渭分明”,但在具體實現上,開始出現融合的趨勢:早期傳統方式是類庫級別的代碼復用,最新趨勢是API Gateway和Sidecar 合二為一。

後者的發展才剛剛起步,包括在螞蟻金服我們也是才開始探索這個方向,但是相信在未來一兩年間,社區可能會有更多的類似產品形態出現。

補充介紹一下文中多次提到的“MOSN”:

MOSN 是 MOSN 是 Modular Open Smart Network 的簡稱, 是一款使用 Go 語言開發的網絡代理軟件,由螞蟻金服開源並經過幾十萬容器的生產級驗證。 MOSN 作為雲原生的網絡數據平面,旨在為服務提供多協議、模塊化、智能化、安全的代理能力。 MOSN 可以與任何支持 xDS API 的 Service Mesh 集成,亦可以作為獨立的四、七層負載均衡,API Gateway、雲原生 Ingress 等使用。

附錄:參考資料和推薦閱讀

意猶未盡的同學,歡迎繼續閱讀以下內容。

按文章發表的時間排序:

  • The Difference Between API Gateways and Service Mesh: 2020-02,指導架構師確定何時使用API​​網關以及何時使用服務網格,作者Marco Palladino,來自kong。
  • Do I Need an API Gateway if I Use a Service Mesh?:2020-01,作者 Christian Posta,中文翻譯版本請見馬若飛同學的 使用了 Service Mesh 後我還需要 API 網關嗎,對 Service Mesh 技術和 API 網關的對比,著重分析了兩者的功能重合點和分歧點,為技術選型和落地提供了指導思路。
  • 螞蟻金服API Gateway Mesh 思考與實踐: 2019-12,作者賈島,介紹螞蟻金服支付寶網關的發展和API Gateway Mesh的由來,強烈推薦閱讀,這個文章非常清晰的介紹了螞蟻金服在Servicemesh和API Gateway融合方面的實踐。
  • API Gateway的身份認同危機: 2019-05, 原文作者 Christian Posta,譯者周雨青,講述API Gateway的基本理念如API的定義,API Management的含義,API Gateway模式,以及服務網格和API Gateway的關係。
  • 長路漫漫踏歌而行:螞蟻金服Service Mesh實踐探索: 2018-10,我在QCon的演講,我分享了當時螞蟻金服在服務間通訊範圍的探索,提出將服務網格在東西向通訊中的能力重用到南北向通訊中,當時基於Sidecar的SOFA Gateway產品剛開始開發。
  • API Gateway vs Service Mesh: 2018-09,作者Richard Li,Datawire的CEO ,在開發 Ambassador API Gateway。 Ambassador 是基於 Envoy 的API Gateway開源產品,文章闡述了對服務網格和API Gateway的看法,差異,以及對兩者集成的看法。
  • DreamMesh拋磚引玉(9)-API Gateway: 2018-03,這個文章也是我寫的,2018年初我和servicemesh社區的一些朋友深入探討之後,在DreamMesh系列博客文章中記錄下了當時構想的方案,尤其對API gateway和sidecar是分是合有詳細討論。當時想法還不夠成熟,但大體方向已經有雛形了。鳴謝當時參與討論的同學!
  • Service Mesh vs API Gateway: 2017-10,原文作者 Kasun Indrasiri,以及 趙化冰同學翻譯的中文版本,文章不長,主要對比了服務網格和API Gateway的產品功能,提出了兩者融合的方式——在API Gateway中通過服務網格來調用下游服務。
  • Application Network Functions With ESBs, API Management, and Now… Service Mesh?:2017-08,作者 Christian Posta,講述服務網格與ESB,消息代理和API管理之類的事物的關係。內容非常好,強烈推薦閱讀(我不得不吐糟一下:配圖太辣眼睛)。