Service Mesh 和 API Gateway 關係深度探討

前言

關於 Service Mesh 和 API Gateway 之間的關係,這個問題過去兩年間常常被問起,社區也有很多文章和資料給出解答。其中不乏 Christian Posta 這樣的網紅給出過深度介紹。我在這裏作一個資料的整理和彙總,結合我的的理解給出一些見解。另外在本文最後,介紹螞蟻金服在 Service Mesh 和 API Gateway 融合的這個最新領域的一些開創性的實踐和探索,但願給你們一個更有體感的認知。前端

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

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

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

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

如上圖所示:api

relationship-without-bff

從功能和職責上說:安全

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

從部署上說:網絡

  • Service Mesh 部署在系統內部:由於原子微服務和組合服務一般不會直接暴露給外部系統;
  • API Gateway 部署在系統的邊緣:一方面暴露在系統以外,對外提供 API 供外部系統訪問;一方面部署在系統內部,以訪問內部的各類服務。

在這裏引入兩個使用很是普遍的術語:架構

directions

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

解釋一下「東西南北」的由來:如上圖所示,一般在地圖上習慣性的遵循「上北下南,左東右西」的原則。app

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

問題的根源在哪裏?框架

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

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

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

relationship-without-bff

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

api-gateway-access-service

因此,API Gateway 做爲一個客戶端訪問內部服務時,到底算南北向仍是東西向,就成爲一個哲學問題:徹底取決於咱們如何看待 API Gateway ,是做爲一個總體,仍是邏輯上分拆爲對內對外兩個部分。

這個哲學問題並不是無厘頭,在 API Gateway 的各類產品中,關於如何實現 「API Gateway 做爲一個客戶端訪問內部服務」 ,就一般分紅兩個流派:

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

而最終決策一般也和產品的定位有關:若是但願維持 API Gateway 的獨立產品定位,但願能夠在不一樣的服務間通信方案下均可以使用,則一般選擇前者,典型如 Kong;若是和服務間通信方案有很是深的淵源,則一般選擇後者,典型如 Spring Cloud 生態下的 Zuul 和 SpringCloud Gateway。

但不管選擇哪一個流派,都改變不了一個事實,當 「API Gateway 做爲一個客戶端訪問內部服務」 時,它的確和一個普通內部服務做爲客戶端去訪問其餘服務沒有本質差別:服務發現、負載均衡、流量路由、熔斷、限流、服務降級、故障注入、日誌、監控、鏈路追蹤、訪問控制、加密、身份認證...... 當咱們把網關訪問內部服務的功能一一列出來時,發現幾乎全部的這些功能都是和服務間調用重複。

這也就形成了一個廣泛現象:若是已有一個成熟的服務間通信框架,再去考慮實現 API Gateway,重用這些重複的能力就成爲天然而然的選擇。典型如前面提到的 Spring Cloud 生態下的 Zuul 以及後面開發的 Spring Cloud Gateway,就是以重用類庫的方式實現了這些能力的重用。

這裏又是一個相似的哲學問題:當 「API Gateway 做爲一個客戶端訪問內部服務」 時,它以重用類庫的方式實現了代碼級別的能力重用,至關於自行實現了一個和普通服務間通信方案徹底同樣的客戶端,那這個「客戶端」發出來的流量算東西向仍是南北向?

答案不重要。

Sidecar:真正的重合點

在進入 Service Mesh 時代以後,Service Mesh 和 API Gateway 的關係開始是這樣:

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

此時二者的關係很清晰,並且因爲當時 Service Mesh 和 API Gateway 是不一樣的產品,二者的重合點只是在功能上。

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

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

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

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

api-gateway-with-service-mesh

這個時候 Service Mesh 和 API Gateway 的關係就變得有意思了,由於 Service Mesh 中 Sidecar 的引入,因此前面的「哲學問題」又有了一個新的解法:API Gateway 此次真的能夠分拆爲兩個獨立部署的物理實體,而不是邏輯上的兩個部分:

  1. API Gateway 本體:實現 API Gateway 除了訪問內部服務以外的功能;
  2. Sidecar:按照 Service Mesh 的標準作法, 咱們視 API Gateway 爲一個部署於 Service Mesh 中的普通服務,爲這個服務 1:1 的部署 Sidecar;

api-gateway-access-service-via-sidecar

在這個方案中,原來用於 Service Mesh 的 Sidecar,被用在了 API Gateway 中,替代了 API Gateway 中原有的客戶端訪問的各類功能。這個方案讓 API Gateway 的實現簡化了不少,也實現了東西向和南北向通信能力的重用和融合,而 API Gateway 能夠更專一於 「API Management」 的核心功能。

此時 Service Mesh 和 API Gateway 的關係就從「涇渭分明」變成了「兼容並濟」。

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

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

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

api-gateway-based-on-sidecar

至於走到這一步以後,Service Mesh 和 API Gateway 是什麼關係:這到底算是 Service Mesh/Sidecar 融合了 API Gateway,仍是 API Gateway 融合了 Service Mesh/Sidecar?這個問題就像斑馬究竟是白底黑紋仍是黑底白紋同樣,見仁見智。

BFF:把融合進行到底

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

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

relationship-with-bff

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

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

「BFF 徹底收口外部流量」,這一點在 API Gateway 和 Sidecar 融合以後,會變得頗有想象空間,咱們先看按照前面的融合方式,在有 BFF 的狀況下,API Gateway 和 Sidecar 融合後的情景:

api-gateway-based-on-sidecar-with-bff

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

two-sidecar-in-bff

注意到,流量從被 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 用:

one-sidecar-in-bff

此時的場景是這樣:

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

bff-api-gateway

注意這裏有一個關鍵點,在前面時特地註明的:「BFF 徹底收口外部流量」。這是前提條件,由於原有的 API Gateway 集羣已經再也不存在,若是 BFF 沒能收口所有流量,則這些未能收口的流量會找不到 API Gateway。固然,若是願意稍微麻煩一點,在部署時清晰的劃定須要暴露給外界的服務,直接在這些服務上部署帶 API Gateway 功能的 Sidecar,也是可行的,只是管理上會比 BFF 模式要複雜一些。

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

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

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

antfin-mesh-gateway

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

總結

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

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

補充介紹一下文中屢次提到的「MOSN」:

MOSN 是 MOSN 是 Modular Open Smart Network 的簡稱, 是一款使用 Go 語言開發的網絡代理軟件,由螞蟻金服開源並通過幾十萬容器的生產級驗證。 MOSN 做爲雲原生的網絡數據平面,旨在爲服務提供多協議、模塊化、智能化、安全的代理能力。 MOSN 能夠與任何支持 xDS API 的 Service Mesh 集成,亦能夠做爲獨立的4、七層負載均衡,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 的由來,強烈推薦閱讀,這個文章很是清晰的介紹了螞蟻金服在 Service Mesh 和 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年初我和 Service Mesh 社區的一些朋友深刻探討以後,在 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 管理之類的事物的關係。內容很是好,強烈推薦閱讀(我不得不吐糟一下:配圖太辣眼睛)。

公衆號:金融級分佈式架構(Antfin_SOFA)

相關文章
相關標籤/搜索