API 網關選型及包含 BFF 的架構設計

一 背景介紹

下圖是我從網絡上找到的一個微服務架構的簡單架構圖,如圖可見 API Gateway 在其中起到一個承上啟下的作用,是關鍵組件。

API 網關選型及包含 BFF 的架構設計

圖片來源於網絡


在更通用的場景下我們會使用 NGINX 這樣的軟件做前置,用來處理SLB負載均衡過來的流量,作用是反向代理、集群負載均衡、轉發、日誌收集等功能。

然後再將 NGINX 的請求 proxy 到 API Gateway 做統一網關處理。

在上面的這個場景下 API Gateway 可以包含以下功能:

  • 安全

  • 限流

  • 緩存

  • 熔斷

  • 重試

  • 負載

  • 反向路由

  • 認證、鑑權

  • 日誌收集和監控

  • 其他

熟悉 NGINX 的朋友應該可以看出來,上面列出的這些功能和 NGINX 的部分功能是重合的,不過由於架構結構不同,在上面我提到的場景中,即 NGINX 在前 API gateway 在後的結構中,他們兩者關注的維度也不一樣,所以即使有重合也正常。

二 架構調整

下圖是我基於雲原生微服務架構設計的架構圖其中前端流量是通過 SLB -> NGINX -> API Gateway 再到具體服務。

API 網關選型及包含 BFF 的架構設計

三 java技術棧的 API Gateway 選型

由於後端採用java 的 spring cloud 開發的,所以在語言一致性上更傾向 java 語言開發的組件。如上圖雖然在 API Gateway 的位置上寫的是 spring cloud gateway,然而也可以採用像 zuul、zuul2 這些同樣是 java 語言開發的組件。對於具體 zuul 和 spring gateway的選型,是這樣考慮的:

API 網關選型及包含 BFF 的架構設計

Spring Cloud Gateway 的性能比 Zuul 好基本上已經是業界公認的了,實際上,Spring Cloud Gateway 官方也發佈過一個性能測試,這裡節選如下數據:

API 網關選型及包含 BFF 的架構設計

Spring Cloud Gateway 構建於 Spring 5+,基於 Spring Boot 2.x 響應式的、非阻塞式的 API。同時,它支持 websockets,和 Spring 框架緊密集成。從目前來看,gateway替代zuul是趨勢。基於以上這些,綜合考慮在架構中使用Spring Cloud Gateway。

四 非java技術棧的 API Gateway 選型

現代 API Gateway 越來越需要或者流行可編程網關了。上面介紹的都是基於 java 語言開發的可編程的 API Gateway。下面我們來聊聊非 java 語言開發的網關。從前面的架構圖上看,我們完全可以將 NGINX 和 API Gateway 合併起來,他們的功能的重合點自然消除了,也能降低架構的複雜性和運維成本。

NGINX 是一款優秀的軟件,然而它在動態性方面的不足導致不太靈活,後面出現的 OpenResty、tengine 這些基於NGINX 和 Lua 的軟件在動態性、靈活方面有本質上的改善,加上基於Lua腳本和插件,可以實現所謂的可編程。

市面上基於OpenResty 以 API Gateway 為應用場景的應用軟件有 Kong、APISIX、tyk 等。以下是CNCFland scape 的一個概覽

API 網關選型及包含 BFF 的架構設計

比較了一下 NGING 和 KONG

API 網關選型及包含 BFF 的架構設計

經過考慮,在架構上,後期有可能將 NGINX、Spring Cloud Gateway 替換成KONG 或其他軟件。

比較了一下,目前最火的應用是Kong,另一個國產的 APISIX 趨勢也是很猛,且他們的技術棧雷同,所以我在選型上找到了APISIX的作者做的對比:

從 API 網關核心功能點來看,兩者均已覆蓋:

API 網關選型及包含 BFF 的架構設計

更詳細的比較:

API 網關選型及包含 BFF 的架構設計

通過性能測試可以看到,在不開啟插件的情況下,Apache APISIX 的性能(QPS 和延遲)是 Kong 的2倍,但開啟了兩個常用插件後,性能就是 Kong 的十倍了。

無論從性能、可用性、可編程代碼量等各個維度APISIX都是非常優秀的,目前唯一擔心的就是這種早期項目沒有太多大規模應用實踐,如果上生產還是有風險,可在測試環境調研,並等待有更多生產實踐作為依據。 當然如果架構師認為風險並不大,且經過了測試調研也是可以上的。

五 BFF 層建設迭代

API 網關選型及包含 BFF 的架構設計

前面我們將 API Gateway 的網關選型介紹了一下,請求通過網關後一般不會直接打到具體微服務上的,而是會通過BFF層,所謂的BFF,即 backend for frontend 面向前端的後端。具體來說它的職能包括:

  • api數據裁剪

  • 接口編排

  • 接口調用

這層有的公司會按業務進行多個BFF的建設,在BFF中又有可能拆成多個服務,比如支撐首頁的,支持列表頁的,或者只有一個服務,支撐某個應用的所有請求的。

有了BFF層,前後端就會更好的解耦,前端不用再調用多個接口,然後再組織數據,微服務後端也只需要關心自己服務邊界內的事情。

然而在實踐的過程中會出現一些問題:

  • 大量業務邏輯從前後端集中在了BFF層

  • BFF層邏輯複雜,代碼量越來越大,難以維護

  • BFF API版本維護複雜

  • 前端端接口職責不清,扯皮的結果就是放在BFF層

以上是我真實遇到過的場景。所以在後面的架構設計和實施中,這些情況會盡量避免,但沒有從技術上解決根本問題。直到 GraphQL 的出現,讓我眼前一亮,給了我一個很好的解決方案。關於GraphQL的搭建,數據交換等細節這裡就不展開說了,感興趣的可以從網上找到很多資料。

下圖是我從網絡上找的一個符合我心目中的理想架構。

API 網關選型及包含 BFF 的架構設計

圖片來源於網絡


說起來簡單,做起來沒那麼容易 ,細節是魔鬼,每利用一個新的技術都會經歷一波打怪升級的過程。不過總體來說利用GraphQL確實能從理論上解決上面所說的問題。而重點是如何將它結合進你的系統架構中,並且發揮出它的優勢。架構很多時候是在做權衡和選擇


分享到:


相關文章: