對於微服務,常見的架構模型就是API網關+服務。
- API網關實現鑒權、負載均衡、中間件等公共入口邏輯。
- 服務實現具體的業務功能。
那么,API網關設計中又有什么坑呢?
1.0版本
直接將服務穿透到外網。
API層只是套了殼,加了鑒權、中間件而已。具體返回值由服務定。
- 客戶端到微服務直接通信,強耦合。根本不敢重構,一改結構客戶端就崩了。
- 需要多次請求,客戶端聚合數據,工作量巨大,延遲高。
- 缺乏統一的文檔。
- 如果一個頁面由多個服務組成,比如商品、優惠券、相關推薦、評價。客戶端要請求多個接口,命名規則還不一樣。
- 有的接口成功,有的接口失敗,需要客戶端自己做降級。
- 協議不利於統一,各個部門間有差異,需要客戶端端來兼容。
- 面向“端”的API適配,耦合到了內部服務。
- 每個服務都要為不同的設備做適配代碼。
- 多終端兼容邏輯復雜,每個服務都需要處理。
- 統一邏輯無法收斂,比如安全認證、限流。
這樣就導致了客戶端、服務端都累得要死,誰都不討好。
而我們的架構設計應該前輕后重的,面向業務場景設計接口,而不是面向數據資源。(不要讓客戶端做組裝)
2.0版本
架構就是一層加一層。
添加了一個BFF層,backend for forntend,專門做適配。
我們新增了一個 app-interface 用於統一的協議出口,在服務內進行大量的 dataset join,按照業務場景來設計粗粒度的 API,給后續服務的演進帶來的很多優勢:
- 輕量交互:協議精簡、聚合。
- 差異服務:數據裁剪以及聚合、針對終端定制化API。
- 動態升級:原有系統兼容升級,更新服務而非協議。
- 溝通效率提升,協作模式演進為移動業務+網關小組。
對接:
大前端---網關,只用對接數據結構。面向業務場景提供接口。
網關---服務,只需要對接服務接口。
BFF可以認為是一種適配服務,將后端的微服務進行適配(主要包括聚合裁剪和格式適配等邏輯),向無線端設備暴露友好和統一的 API,方便無線設備接入訪問后端服務。
針對頁面提供接口,比如商品頁面,就一個接口,然后BFF層去調用多個服務,在這里做降級,比如優惠券服務沒有返回就不顯示就完了。
客戶端只用和BFF層溝通,什么適配、協議、兼容、定制都是這一層來做。客戶端感覺很爽。
服務端也只用提供基礎數據,不用關心業務邏輯,不用管適配,返回的接口是什么結構。服務端也很爽。
BFF層只做了數據裁剪,兼容之類的邏輯,輕不輕松?也很輕松。
問題:
- BFF單點了,single point of failure(單點故障)。也就是所有的流量都會到這一層, 如果有流量洪峰或者代碼有bug,全盤宕機。
3.0版本
將BFF根據業務拆分,比如查看商品一個,訂單頁面一個。這樣一個掛不會影響全局。
問題
- 單個模塊也會導致后續業務集成復雜度高,根據康威法則,單塊的無線BFF和多團隊之間就出現不匹配問題,團隊之間溝通協調成本高,交付效率低下。
- 很多跨橫切面邏輯,比如安全認證,日志監控,限流熔斷等。隨着時間的推移,代碼變得越來越復雜,技術債越堆越多。
有沒有發現:
分久必合、合久必分。
分開了就有不能統一的地方,合並了就會單點故障。
4.0版本
跨橫切面(Cross-Cutting Concerns)的功能,需要協調更新框架升級發版(路由、認證、限流、安全),因此全部上沉,引入了 API Gateway,把業務集成度高的 BFF 層和通用功能服務層 API Gateway 進行了分層處理。
在新的架構中,網關承擔了重要的角色,它是解耦拆分和后續升級遷移的利器。
在網關的配合下,單塊 BFF 實現了解耦拆分,各業務線團隊可以獨立開發和交付各自的微服務,研發效率大大提升。
BFF的划分:
- 重要性
- 垂直業務,閉環
- 流量大小
另外,把跨橫切面邏輯從 BFF 剝離到網關上去以后,BFF 的開發人員可以更加專注業務邏輯交付,實現了架構上的關注分離(Separation of Concerns)。
我們業務流量實際為:
移動端 -> API Gateway -> BFF -> Mircoservice
在 FE Web業務中,BFF 可以是 nodejs 來做服務端渲染(SSR,Server-Side Rendering),注意這里忽略了上游的 CDN、4/7層負載均衡(ELB)。
將通用邏輯做到了API網關層,BFF層專注於業務邏輯。
API層采用Nginx這種高可用的軟件,基本不會掛,掛了重啟即可,限流、負載等邏輯用模塊實現,方便部署。
這一層完全和業務無關。
總結
當耦合性太高的時候,就加一層,作為緩沖。
當合並有單點的時候,就分開。當分開有不能統一的時候,就合並。
盡量讓專門的人做專門的事情。減少業務對技術的耦合。