一 背景介紹
下圖是我從網絡上找到的一個微服務架構的簡單架構圖,如圖可見 API Gateway 在其中起到一個承上啟下的作用,是關鍵組件。
圖片來源于網絡
在更通用的場景下我們會使用 Nginx 這樣的軟件做前置,用來處理SLB負載均衡過來的流量,作用是反向代理、集群負載均衡、轉發、日志收集等功能。
然后再將 NGINX 的請求 proxy 到 API Gateway 做統一網關處理。
在上面的這個場景下 API Gateway 可以包含以下功能:
- 安全
- 限流
- 緩存
- 熔斷
- 重試
- 負載
- 反向路由
- 認證、鑒權
- 日志收集和監控
- 其他
熟悉 NGINX 的朋友應該可以看出來,上面列出的這些功能和 NGINX 的部分功能是重合的,不過由于架構結構不同,在上面我提到的場景中,即 NGINX 在前 API gateway 在后的結構中,他們兩者關注的維度也不一樣,所以即使有重合也正常。
二 架構調整
下圖是我基于云原生微服務架構設計的架構圖其中前端流量是通過 SLB -> NGINX -> API Gateway 再到具體服務。
三 JAVA技術棧的 API Gateway 選型
由于后端采用java 的 spring cloud 開發的,所以在語言一致性上更傾向 java 語言開發的組件。如上圖雖然在 API Gateway 的位置上寫的是 spring cloud gateway,然而也可以采用像 zuul、zuul2 這些同樣是 java 語言開發的組件。對于具體 zuul 和 spring gateway的選型,是這樣考慮的:
Spring Cloud Gateway 的性能比 Zuul 好基本上已經是業界公認的了,實際上,Spring Cloud Gateway 官方也發布過一個性能測試,這里節選如下數據:
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 的一個概覽
比較了一下 NGING 和 KONG
經過考慮,在架構上,后期有可能將 NGINX、Spring Cloud Gateway 替換成KONG 或其他軟件。
比較了一下,目前最火的應用是Kong,另一個國產的 APISIX 趨勢也是很猛,且他們的技術棧雷同,所以我在選型上找到了APISIX的作者做的對比:
從 API 網關核心功能點來看,兩者均已覆蓋:
更詳細的比較:
通過性能測試可以看到,在不開啟插件的情況下,Apache APISIX 的性能(QPS 和延遲)是 Kong 的2倍,但開啟了兩個常用插件后,性能就是 Kong 的十倍了。
無論從性能、可用性、可編程代碼量等各個維度APISIX都是非常優秀的,目前唯一擔心的就是這種早期項目沒有太多大規模應用實踐,如果上生產還是有風險,可在測試環境調研,并等待有更多生產實踐作為依據。 當然如果架構師認為風險并不大,且經過了測試調研也是可以上的。
五 BFF 層建設迭代
前面我們將 API Gateway 的網關選型介紹了一下,請求通過網關后一般不會直接打到具體微服務上的,而是會通過BFF層,所謂的BFF,即 backend for frontend 面向前端的后端。具體來說它的職能包括:
- api數據裁剪
- 接口編排
- 接口調用
這層有的公司會按業務進行多個BFF的建設,在BFF中又有可能拆成多個服務,比如支撐首頁的,支持列表頁的,或者只有一個服務,支撐某個應用的所有請求的。
有了BFF層,前后端就會更好的解耦,前端不用再調用多個接口,然后再組織數據,微服務后端也只需要關心自己服務邊界內的事情。
然而在實踐的過程中會出現一些問題:
- 大量業務邏輯從前后端集中在了BFF層
- BFF層邏輯復雜,代碼量越來越大,難以維護
- BFF API版本維護復雜
- 前端端接口職責不清,扯皮的結果就是放在BFF層
以上是我真實遇到過的場景。所以在后面的架構設計和實施中,這些情況會盡量避免,但沒有從技術上解決根本問題。直到 GraphQL 的出現,讓我眼前一亮,給了我一個很好的解決方案。關于GraphQL的搭建,數據交換等細節這里就不展開說了,感興趣的可以從網上找到很多資料。
下圖是我從網絡上找的一個符合我心目中的理想架構。
圖片來源于網絡
說起來簡單,做起來沒那么容易 ,細節是魔鬼,每利用一個新的技術都會經歷一波打怪升級的過程。不過總體來說利用GraphQL確實能從理論上解決上面所說的問題。而重點是如何將它結合進你的系統架構中,并且發揮出它的優勢。