Service Mesh 和 API Gateway 關係深度探討

# 前言

關於 Service Mesh 和 API Gateway 之間的關係,這個問題過去兩年間經常被問起,社區也有不少文章和資料給出解答。其中不乏 Christian Posta 這樣的網紅給出過深度介紹。我在這裏做一個資料的整理和彙總,結合個人的理解給出一些看法。

備註 1:爲了節約篇幅,我們將直奔主題,假定讀者對 Service Mesh 和 API Gateway 已有基本的瞭解。

備註 2:  這邊文章更關注於梳理整個脈絡,內容不會展開的特別細,尤其是其他文章已經詳細闡述的部分。如果您在瀏覽本文之後,還想更深入的瞭解細節,請繼續閱讀文章最後的參考資料和推薦閱讀。

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

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

如上圖所示:

從功能和職責上說:

從部署上說:

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

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

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

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

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

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

所以,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 這種東西向通訊的方案。這裏我們不展開細節,我這裏援引一個圖片 (鳴謝趙化冰同學) 來解釋這個方案的思路:

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

在這個方案中,原來用於 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 再次合二爲一:

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

# BFF:把融合進行到底

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

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

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

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

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

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

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

此時的場景是這樣:

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

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

# 總結

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

後者的發展纔剛剛起步,但是相信在未來一兩年間,社區可能會有更多的類似產品形態出現。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/luHl_yV3A51lrFlWF6wOVQ