關(guān)于 BFF 架構(gòu)設(shè)計的胖瘦之爭
一、什么是BFF
最開始,我們還是先明確下BFF是什么吧,由于前文已經(jīng)做過介紹了,這里就簡單的提一下。
BFF:Backends For Frontends(服務(wù)于前端的后端)。
BFF是一種Web架構(gòu),微服務(wù)設(shè)計系列叢書的作者 Sam Newman曾在他的博客中寫了一篇相關(guān)文章《Pattern: Backends For Frontends》。
BFF 的概念最初就是來源于此。
圖片
服務(wù)端設(shè)計API時會考慮到不同設(shè)備的需求,即為不同設(shè)備提供不同API接口,雖然它們可能實現(xiàn)相同功能,但因不同設(shè)備的特殊性,它們對服務(wù)端的API訪問也各有其特點,需區(qū)別處理。在計算機(jī)科學(xué)中,所有問題都可以通過加一層來解決,于是 BFF 架構(gòu)設(shè)計應(yīng)運(yùn)而生。
2. BFF的胖瘦之爭
在現(xiàn)代軟件開發(fā)中,服務(wù)化可能是解決大型復(fù)雜應(yīng)用的必然之路,BFF 架構(gòu)已成為構(gòu)建高效、靈活前端應(yīng)用的重要手段之一。
在服務(wù)化的系統(tǒng)中規(guī)劃階段,有一些必然會被討論的話題:
要不要 BFF 層? 要不要編排層?
要不要網(wǎng)關(guān)?什么是網(wǎng)關(guān)?
應(yīng)用網(wǎng)關(guān)和網(wǎng)關(guān)的區(qū)別是什么?
后端(領(lǐng)域服務(wù))服務(wù)之間要不要互相調(diào)用?
要不要使用 BFF 來編排后端服務(wù)?
BFF 是不是編排層?
BFF 能不能宏觀上對應(yīng) DDD 的應(yīng)用層?
......
在上面這些問題中,最讓人關(guān)心的問題倒不是響應(yīng)用戶請求流量的服務(wù)叫是 ServiceA 還是 ServiceB,而是它應(yīng)該直接轉(zhuǎn)發(fā)數(shù)據(jù)還是需要為每個 API 重新編寫一次實現(xiàn),并調(diào)用后端 API。
然而,對于 BFF 架構(gòu)的設(shè)計,存在著 “胖” 與 “瘦” 的不同考量,這會決定我們在 BFF 中是否需要編寫大量代碼,所以我把它們的區(qū)別稱之為"胖瘦 BFF"。
概括而言:不同 BFF 的考量會決定微服務(wù)架構(gòu)的兩種形態(tài)。
3. 胖 BFF
在有一些架構(gòu)形態(tài)中,BFF 會有以下職責(zé):
- 鑒權(quán)
- 限流、熔斷、服務(wù)降級、灰度路由等
- 接入多種協(xié)議和設(shè)備,比如 MQTT 服務(wù)、WebSocket 等
- 編排領(lǐng)域服務(wù),盡量避免后端服務(wù)之間互相依賴,統(tǒng)一由 BFF 處理
- 不同類型的客戶端一套 BFF
- 非常接近 DDD 四層架構(gòu)中的應(yīng)用層,處理面向場景的業(yè)務(wù)
因為它的職責(zé)比較多,我們暫且稱其為:胖 BFF。
胖 BFF 的特點是:
- 強(qiáng)大的業(yè)務(wù)邏輯處理能力:胖 BFF 架構(gòu)不僅可以進(jìn)行數(shù)據(jù)轉(zhuǎn)換,還可以承擔(dān)更多的業(yè)務(wù)邏輯處理。它可以整合多個后端服務(wù)的數(shù)據(jù),進(jìn)行復(fù)雜的計算和業(yè)務(wù)規(guī)則校驗。
- 高度定制化:能夠根據(jù)不同的前端需求進(jìn)行深度定制,為不同的用戶界面提供個性化的數(shù)據(jù)和服務(wù)。
- 更好的性能優(yōu)化:可以對數(shù)據(jù)進(jìn)行緩存、預(yù)取等優(yōu)化操作,提高前端應(yīng)用的性能。
胖 BFF 的好處是:
- 可以對不同類型的客戶端定制一套 API,且各自之間不受干擾
- 領(lǐng)域服務(wù)可以設(shè)計得比較原子化,比較少的侵入特定場景信息到領(lǐng)域服務(wù)中
- 容易適配更多類型的客戶端
- 比較容易實現(xiàn)個性化的鑒權(quán)、特定用戶群的交互邏輯
- 方便實現(xiàn)準(zhǔn)確、統(tǒng)一的 API 文檔
但是這類架構(gòu)也有非常多的弊端,導(dǎo)致很多架構(gòu)師非??咕埽?/p>
- 破壞了端到端交付能力,如果按照上下文劃分微服務(wù),剛好這些微服務(wù)和前端業(yè)務(wù)和需求對應(yīng),那么跨功能團(tuán)隊的交付效率會更高
- 重復(fù)勞動,一些接口的模型不僅在領(lǐng)域服務(wù)實現(xiàn)一次,還需要在 BFF 做一次
- 難以分工,維護(hù)后端服務(wù)的人員都會和這個服務(wù)集成
在海外的一些文章和書籍中,他們也會有類似的困惑。很多架構(gòu)師把這種結(jié)構(gòu)叫做編排(Orchestration)。
圖片
4. 瘦 BFF
相對而言,瘦 BFF 架構(gòu),其職責(zé)可能更少:
- 鑒權(quán)
- 透明轉(zhuǎn)發(fā)流量到后端服務(wù)
- 和胖 BFF 類似,也有限流、熔斷、服務(wù)降級、灰度路由等職責(zé)
瘦 BFF 的特點:
- 簡潔高效:瘦 BFF 架構(gòu)專注于將后端服務(wù)的數(shù)據(jù)進(jìn)行輕量級的轉(zhuǎn)換和適配,以滿足前端的需求。它通常只進(jìn)行必要的數(shù)據(jù)篩選、格式轉(zhuǎn)換和簡單的業(yè)務(wù)邏輯處理。
- 快速響應(yīng):由于功能相對簡單,瘦 BFF 可以快速響應(yīng)前端的請求,減少延遲,提高用戶體驗。
- 易于維護(hù):代碼量較少,結(jié)構(gòu)清晰,使得維護(hù)成本相對較低。開發(fā)人員可以更容易地理解和修改代碼,快速定位和解決問題。
瘦 BFF 的好處是:
- 端到端交付,前端開發(fā)人員直接使用后端領(lǐng)域服務(wù)的 API 文檔
- 開發(fā)效率高,避免多編寫一層 BFF
- 減少一次集成
對應(yīng)的,瘦 BFF 的弊端可想而知:
- 沒有編排層,服務(wù)之間相互依賴
- 編排行為落入前端或者領(lǐng)域服務(wù),拓展性差
- 領(lǐng)域服務(wù)之間調(diào)用關(guān)系復(fù)雜
- 領(lǐng)域服務(wù)職責(zé)過多,侵入業(yè)務(wù)場景,難以被復(fù)用
這樣的話,BFF 僅僅扮演轉(zhuǎn)發(fā)的作用,也就成了我們口中的網(wǎng)關(guān)。
圖片
5. 兩種形態(tài)的權(quán)衡
那么在什么場景下,更合理的選擇這兩種結(jié)構(gòu)之一呢?
- 1. 業(yè)務(wù)需求
如果業(yè)務(wù)邏輯簡單,數(shù)據(jù)交互相對較少,瘦 BFF 可能就足夠滿足需求。但如果業(yè)務(wù)復(fù)雜,需要進(jìn)行大量的業(yè)務(wù)邏輯處理和數(shù)據(jù)整合,胖 BFF 則更為合適。
- 2. 開發(fā)團(tuán)隊規(guī)模和技能
瘦 BFF 相對容易開發(fā)和維護(hù),適合小型開發(fā)團(tuán)隊或技術(shù)能力有限的團(tuán)隊。而胖 BFF 需要更高的技術(shù)水平和更多的開發(fā)資源,適合有經(jīng)驗的大型開發(fā)團(tuán)隊。
- 3. 項目周期和迭代速度
對于短期項目或需要快速迭代的項目,瘦 BFF 可以更快地實現(xiàn)并投入使用。而胖 BFF 的開發(fā)周期可能較長,但在長期運(yùn)行中可以提供更好的性能和可維護(hù)性。
- 4. 可擴(kuò)展性
考慮未來業(yè)務(wù)的發(fā)展和擴(kuò)展需求。如果預(yù)計業(yè)務(wù)會不斷增長,功能會逐漸復(fù)雜,選擇胖 BFF 可以為未來的擴(kuò)展提供更好的基礎(chǔ)。
圖片
6. 總結(jié)
總之,BFF 架構(gòu)的胖瘦之分并沒有絕對的標(biāo)準(zhǔn),需要根據(jù)具體的項目需求、業(yè)務(wù)特點和開發(fā)團(tuán)隊情況進(jìn)行綜合考慮。
無論是胖瘦 BFF,其實都是基于場景對單體系統(tǒng)拆分的結(jié)果,非常依賴于所屬場景。
在實際應(yīng)用中,可以根據(jù)不同的階段和需求,靈活地調(diào)整 BFF 的設(shè)計,以實現(xiàn)最佳的用戶體驗和系統(tǒng)性能,這也解釋了關(guān)于 BFF 為什么目前還沒有形成統(tǒng)一的技術(shù)方案和觀念。