大廠為啥都要用Node去寫中間層(BFF)呢?
作者:漂流瓶jz
https://juejin.cn/post/7240404579133128760
BFF是一種Web架構(gòu),全名為Backends For Frontends,即為服務(wù)于前端的后端。這個(gè)詞來源于Sam Newman的一篇文章:Pattern: Backends For Frontends[1]。BFF一般指的是在前端與后端之間加增加一個(gè)中間層。為什么要在前端和后端之間增加一個(gè)BFF層呢?
計(jì)算機(jī)科學(xué)家David Wheeler曾經(jīng)說過一句話:All problems in computer science can be solved by another level of indirection.計(jì)算機(jī)科學(xué)中的所有問題都可以通過加一層來解決。因此,需要使用BFF的場景,肯定是普通的前后端開發(fā)模式遇到了部分問題。例如在Sam Newman的文章中就描述了BFF解決多個(gè)展示端的場景。
多端展示問題
在系統(tǒng)一開始開發(fā)的時(shí)候只考慮了PC網(wǎng)頁端的設(shè)計(jì),服務(wù)器端API是為了PC網(wǎng)頁端而服務(wù)的。但是后來隨著移動(dòng)互聯(lián)網(wǎng)的興起,移動(dòng)端開始流行,決定在原有服務(wù)端的基礎(chǔ)上開發(fā)移動(dòng)端App,復(fù)用之前的API,但是原有API是為了PC端設(shè)計(jì)的,并不符合移動(dòng)端的需求。
-
PC端的需求與移動(dòng)端并不一定完全相同,現(xiàn)有接口無法滿足所有移動(dòng)端的新需求。 -
PC端電腦性能強(qiáng),可以并發(fā)請求多個(gè)接口或進(jìn)行部分較復(fù)雜的數(shù)據(jù)處理,但是移動(dòng)端性能低,如果使用同樣的多個(gè)接口,由前端組裝數(shù)據(jù),頁面展示可能會(huì)出現(xiàn)延遲和卡頓現(xiàn)象。 -
PC端的屏幕較大,展示內(nèi)容較多且全面。但是移動(dòng)端屏幕小,展示內(nèi)容較少。而且部分?jǐn)?shù)據(jù)的獲取并不容易,需要后端調(diào)用許多服務(wù)。如果移動(dòng)端復(fù)用PC端接口,會(huì)獲取和傳輸部分無用數(shù)據(jù),不僅消耗服務(wù)端資源,還浪費(fèi)網(wǎng)絡(luò)帶寬。
而且隨著科技的發(fā)展和用戶的需求,不同的展示端越來越多,在不僅在手機(jī)上會(huì)區(qū)分Android端,IOS端,而且還會(huì)有平板電腦端,手機(jī)網(wǎng)頁端,PC網(wǎng)頁端,PC的APP端等等。這些端的頁面設(shè)計(jì)各不相同,對(duì)于數(shù)據(jù)的需求也不相同。假設(shè)我們復(fù)用同一個(gè)服務(wù)端和API接口,如果出現(xiàn)不滿足需求的場景就加接口加字段,那么隨著這些不同客戶端的開發(fā)和迭代,服務(wù)端會(huì)變的大而臃腫,效率低下。而且同一個(gè)接口提供給太多前端調(diào)用,涉及到太多的邏輯,復(fù)雜性越來越高。
因此,更好的方式是服務(wù)端對(duì)展示進(jìn)行解耦,服務(wù)端只負(fù)責(zé)提供數(shù)據(jù),有專門的展示端負(fù)責(zé)前端的展示業(yè)務(wù)。這里的展示端就是BFF層。
不同業(yè)務(wù)場景的展示模式差異
在某些業(yè)務(wù)中,客戶端的類型只有一種,但是在不同的場景下,展示的模式有差異。比如在美團(tuán)的BFF實(shí)踐中,不同行業(yè)的團(tuán)購貨架展示模塊不同,是兩套獨(dú)立定義的產(chǎn)品邏輯,并且會(huì)各自迭代。
在這種業(yè)務(wù)場景下,雖然是同一個(gè)客戶端,但是業(yè)務(wù)不同,需求的數(shù)據(jù)格式和類型也不同,因此遇到與上面多端展示類似的接口問題。
短生命周期的需求
還有一種情形,是閑魚團(tuán)隊(duì)遇到的短生命周期的需求。在普通的業(yè)務(wù)場景下,服務(wù)端正常穩(wěn)定迭代開發(fā)。但是偶爾會(huì)有一些特殊的運(yùn)營活動(dòng),這種活動(dòng)時(shí)間較短,可能僅僅持續(xù)幾天時(shí)間。
如果僅僅為了這些幾天的活動(dòng),每次都要開新API,聯(lián)調(diào),甚至修改原有服務(wù)端的邏輯,成本較大,而且較為低效。如果加一層BFF,讓前端可以直接獲取數(shù)據(jù),那么開發(fā)和聯(lián)調(diào)會(huì)變的簡單很多。
業(yè)務(wù)整合需要
在某些情形下,業(yè)務(wù)后端和需求比較復(fù)雜,例如這篇文章涉及到的場景[2],有一個(gè)Moments App,包含了像用戶管理,關(guān)系管理,信息,頭像,點(diǎn)贊等多種多種后端微服務(wù)。這些服務(wù)在前端展示的邏輯耦合性較強(qiáng)。比如有些需要串行處理,例如得到服務(wù)1的結(jié)果才可以調(diào)用服務(wù)2;有些則可以并行處理。而數(shù)據(jù)合并和整理的邏輯額較為復(fù)雜。
圖片來源:跨平臺(tái)架構(gòu):如何設(shè)計(jì) BFF 架構(gòu)系統(tǒng)?[3]
網(wǎng)易云音樂也使用BFF進(jìn)行微服務(wù)的調(diào)度以及數(shù)據(jù)的組裝和適配。
圖片來源:基于 GraphQL 的云音樂 BFF 建設(shè)實(shí)踐[4]
這時(shí)候可以設(shè)立一個(gè)BFF層,作為一個(gè)數(shù)據(jù)整合服務(wù),將調(diào)用不同微服務(wù)接口,與數(shù)據(jù)處理的復(fù)雜邏輯都在BFF端中實(shí)現(xiàn),降低了前端的復(fù)雜度,也提高了響應(yīng)效率。
處理部分展示相關(guān)的業(yè)務(wù)
在使用了BFF之后,部分頁面展示相關(guān)的業(yè)務(wù)邏輯可以抽象出來,交由BFF端處理。
例如數(shù)據(jù)導(dǎo)出Excel下載服務(wù),輸入導(dǎo)入Excel上傳服務(wù)。BFF層可以接收用導(dǎo)入的Excel,解析并處理表格數(shù)據(jù),然后提供給服務(wù)端。在導(dǎo)出時(shí),也可以調(diào)用服務(wù)端API獲取數(shù)據(jù),由BFF端整合提供給前端下載。在這種情形下,服務(wù)端只需要提供一個(gè)展示接口,就可以滿足頁面展示和導(dǎo)出兩種不同格式的展示需求。導(dǎo)入也是同理。而且假設(shè)表格與頁面展示要求的數(shù)據(jù)格式不同,例如導(dǎo)入時(shí)部分字段值需要作轉(zhuǎn)換,那么也可以由BFF端處理這種差異。
BFF的類型
BFF本身僅僅是一個(gè)概念,實(shí)現(xiàn)方式有多種,在實(shí)際中我們要根據(jù)不同的場景選取不同的方案。按照大類分,主要有單一BFF和多端BFF。
單一BFF
單一的BFF主要對(duì)接服務(wù)端,根據(jù)展示服務(wù)的需求組裝數(shù)據(jù)提供給每個(gè)端或者每種業(yè)務(wù)進(jìn)行展示。
很多單一BFF都會(huì)用到GraphGL,他是由Facebook開發(fā)的數(shù)據(jù)查詢工具。通過該工具,可以將不穩(wěn)定的數(shù)據(jù)組裝部分從穩(wěn)定的業(yè)務(wù)數(shù)據(jù)邏輯中剝離,使數(shù)據(jù)控制邏輯前移,開發(fā)模式由“下發(fā)數(shù)據(jù)”轉(zhuǎn)變成“取數(shù)據(jù)”的過程。
例如美團(tuán),閑魚,網(wǎng)易云音樂等的BFF,都提供了按需查詢能力,一個(gè)BFF對(duì)接多種客戶端或者多種業(yè)務(wù)的需求。下圖是美團(tuán)使用的BFF架構(gòu)設(shè)計(jì)。
圖片來源:GraphQL及元數(shù)據(jù)驅(qū)動(dòng)架構(gòu)在后端BFF中的實(shí)踐
多端BFF
多端BFF是指每種業(yè)務(wù)或者每種客戶端采用自己獨(dú)立的BFF層,這樣每種客戶端的服務(wù)更加靈活,不同的BFF端對(duì)于展示服務(wù)解耦性更高。
前端BFF與后端BFF
從技術(shù)上分,BFF又可以分為前端BFF和后端BFF。即BFF層由前端團(tuán)隊(duì)主導(dǎo)或者后端團(tuán)隊(duì)主導(dǎo)。前端團(tuán)隊(duì)的BFF一般使用Node.js,后端團(tuán)隊(duì)則會(huì)使用Java或者其他服務(wù)端語言。
如果使用前端BFF,可以實(shí)現(xiàn)誰使用誰開發(fā),一定程序生避免了前后端實(shí)現(xiàn)的上不必要的溝通成本。但需要前端團(tuán)隊(duì)有一服務(wù)端開發(fā)經(jīng)驗(yàn),對(duì)前端團(tuán)隊(duì)的技術(shù)建設(shè)有較高需求。但是前端也能更深入的接觸業(yè)務(wù)邏輯,對(duì)于重展示的業(yè)務(wù)需求有一定優(yōu)勢。例如淘寶的實(shí)踐:大淘寶技術(shù)行業(yè)FaaS化實(shí)戰(zhàn)經(jīng)驗(yàn)分享[5]。
傳統(tǒng)接口與按需查詢
傳統(tǒng)接口模式即正常開發(fā)接口,固定入?yún)⒑头祷財(cái)?shù)據(jù)格式,供前端調(diào)用。按需查詢模式即前端調(diào)用接口時(shí)指定需要哪些數(shù)據(jù),前端自主進(jìn)行按需查詢。GraphQL即是使用按需查詢的模式。
BFF的其他特點(diǎn)
與ServerLess集成
使用前端BFF時(shí),前端開發(fā)可能缺乏運(yùn)維經(jīng)驗(yàn),而且在高可用,并發(fā)性等問題上可能會(huì)遇到挑戰(zhàn)。如果結(jié)合Serverless實(shí)現(xiàn)自動(dòng)擴(kuò)容,彈性伸縮等功能,可以解決一些BFF的問題。
阿里云的云原生團(tuán)隊(duì)介紹了這一方法:基于函數(shù)計(jì)算的 BFF 架構(gòu)[6](圖片來源)
BFF與網(wǎng)關(guān)
網(wǎng)關(guān)可以提供路由,認(rèn)證,監(jiān)控,日志等服務(wù)。網(wǎng)關(guān)可以與BFF集成在一起,也可以作為獨(dú)立的一層來實(shí)現(xiàn)。如果業(yè)務(wù)復(fù)雜,還可以在不同的BFF上層配置不同的網(wǎng)關(guān)。
這篇文章介紹了在不同場景下,BFF層與網(wǎng)關(guān)的應(yīng)用。微服務(wù)架構(gòu):BFF和網(wǎng)關(guān)是如何演化出來的?[7](圖片來源)
BFF的優(yōu)勢
通過上面的的各種問題和場景,相信我們已經(jīng)知道了BFF可以解決很多場景的問題,這里總結(jié)一下BFF的優(yōu)勢:
-
服務(wù)端對(duì)數(shù)據(jù)展示服務(wù)進(jìn)行解耦,展示服務(wù)由獨(dú)立的BFF端提供,服務(wù)端可以聚焦于業(yè)務(wù)處理。 -
多端展示或者多業(yè)務(wù)展示時(shí),對(duì)與數(shù)據(jù)獲取有更好的靈活性,避免數(shù)據(jù)冗余造成消耗服務(wù)端資源。 -
對(duì)于復(fù)雜的前端展示,將數(shù)據(jù)獲取和組裝的負(fù)責(zé)邏輯在BFF端執(zhí)行,降低前端處理的復(fù)雜度,提高前端頁面響應(yīng)效率。 -
部分展示業(yè)務(wù),可以抽象出來利用BFF實(shí)現(xiàn),對(duì)于服務(wù)端實(shí)現(xiàn)接口復(fù)用。 -
降低多端業(yè)務(wù)的耦合性,避免不同端業(yè)務(wù)開發(fā)互相影響。 -
其他優(yōu)勢,包括數(shù)據(jù)緩存,接口安全校驗(yàn)等。
向下滑動(dòng)查看
