架構-初識BFF

LemonDus發表於2024-12-08

引言

晚上公司開了一個技術分享會,主要內容就是公司的專案架構,會中講解了專案整體架構是BFF架構,就是在微服務之上多加了一層。

除此之外,還講解了DDD設計思想,主要用於各個業務中臺,如訂單中臺、使用者中臺等。

這是我的架構第一課,聽得有些似懂非懂,於是淺淺地整理一下。

BFF

是什麼

BFF是服務於前端的後端,全稱Backend For Frontend。BFF的位置在與客戶端與服務端中間,起到一箇中介軟體的作用,我在聽的過程中更覺得像是一個前端與後端之間的閘道器。

為什麼使用

BFF是近些年新衍生出來的一種開發模式,或者說是一種適配模式的系統,為了適配微服務模式下前端後端系統介面呼叫混亂而出現的。

在如今微服務盛行的趨勢下,大型系統中劃分出了數十個服務模組,例如商品,門店,運費,紅包,訂單,優惠券,CMS,使用者,搜尋,推薦,廣告等等系統,前端也有小程式,APP,網頁等端。由此產生了很多問題:

  • 前端問題:每次需求開發前端要對接多個系統來確認介面資訊,不同的資料要找不同的系統,各個介面散落一地,開發除錯的效率極低。
  • 後端問題:後端同樣也需要各自包裝資料資訊來提供前端處理,重心變成如何為前端提供資料,因為需要根據不同的版本、客戶端、使用者、定位等特徵來判別,很多時間浪費在展示層,而不能專注於業務邏輯處理,每個後端系統各自為戰,都有自己的介面規則,各種歷史版本問題都不能完全統一,所有系統都嚴重耦合了版本問題。
  • 變更不靈活:當產品想要更新需求時,更是牽一髮而動全身,某一塊的小改動需要在各個系統之間找介面來回溝通,大部分系統都要重新上線一次。

如下圖所示,未啟用BFF架構之前,前後端的溝通鏈路過多。
bff1

BFF的閘道器定位

鑑於以上痛點,需要一箇中間層來適配前後端服務,BFF由此而生,它負責將所有下游後端介面進行統一呼叫,下游介面只需要提供RPC介面供閘道器使用,BFF閘道器提供Web介面來讓前端呼叫,最後將資料進行組裝拼接,根據前端的需求來返回資料。

所以BFF的核心定位就是:“統一下游介面,為前端提供服務”。

只有把握好服務這個概念,才能做好BFF閘道器係統,其他系統可以扯皮甩鍋,但BFF閘道器不可以,它與生俱來的使命就是把這兩邊拉扯起來,所有不合理不合適,繁瑣無用的邏輯都需要BFF閘道器去處理,後端只要做好業務邏輯,前端做好展示,其他的都可以交給BFF閘道器。
bff2

BFF閘道器特點

BFF作為一種特殊閘道器,還有以下特點:

瑣碎

BFF閘道器主要為前端進行服務,前端不關心版本、客戶端、定位、使用者身份等情況,只接收渲染資料即可,而這些邏輯都需要耦合到BFF閘道器中,以版本、客戶端、定位、使用者等特徵作為緯度,其中版本最為最複雜的分支,可能貫徹整個系統生涯幾十個版本型別都需要做相容,由此還需要兼顧不同客戶端的展示要求和使用者特徵,所以BFF閘道器中必然需要做大量判斷分支,根據上百種情況組合判斷來生成-唯一版本-唯一端-唯一使用者的資料結構。

資料瑣碎

BFF不需要資料庫,這點會在下面說明,所以有很多資料需要以靜態變數的形式存放在程式碼裡,或者是使用配置中心來動態配置,例如圖片地址、各種色值、模組固定文字、處理標識等,這些瑣碎的資料都會存放在BFF閘道器中進行維護,如果放在前端,修改時必須要進行發版,時間週期太長,而存放在後端的話,又會打散資料,不能從一個地方作為主要資料視窗進行管理。

邏輯瑣碎

衍生第一點說到的,BFF閘道器作為下游介面的聚合,每次流程需要呼叫數十個後端介面,再根據版本、端、使用者進行邏輯處理,歷史邏輯與新需求雜糅在一起,實現新功能的同時要不斷兼顧歷史邏輯,只能是加入大量的分支判斷,最後變成了if大爆炸,或者使用策略模式進行最佳化,但無論如何怎麼包裝都無法掩蓋瑣碎的邏輯。

效能

BFF閘道器的耗時主要有兩部分:

  • 內部處理耗時
  • 下游RPC介面耗時

BFF作為最直接和前端互動的介面,BFF的耗時將直接影響使用者瀏覽體驗,所以BFF效能一定要最優,不斷壓縮耗時來提高介面響應效能,內部邏輯最佳化時,首先觀察下游介面耗時情況,各個模組之間難免重複呼叫介面,可以使用編排框架將下游介面呼叫進行最佳化。然後使用執行緒池進行併發處理,能夠併發處理的一定要併發執行,這樣可以極大降低下游介面耗時,提供介面處理能力。

快取

切勿在BFF閘道器中使用快取

此處指的快取主要是Redis等中介軟體快取,BFF閘道器主要資料來源都是透過呼叫下游介面獲取,這裡是最耗時的,如果想要減少下游介面耗時,應該使用併發或者編排能力,而不可以透過快取下游介面資料來實現。

  • 成本問題:下游介面資料會根據傳入的定位、使用者等資訊查詢,當系統使用者量大、覆蓋城市多時,需要快取的資料量將劇增,而資料快取後再次訪問機率很低,造成嚴重的快取空間浪費。
  • 一致性問題:BFF閘道器的引入主要是為了統一後端介面,效能是閘道器的一大指標,但不能為了效能將所有下游介面資料進行快取,從而犧牲資料一致性,後續展示時一旦出現問題,將增加排查難度。

降級
bff3

任何時候都不要將錯誤直接返回給使用者,不論是下游的錯誤還是系統內部的錯誤,這一點完全可以交給BFF閘道器來做,這裡降級可以分為兩型別處理。

  • 下游介面降級:當下遊介面出現超時或資料異常時,一定要做好降級措施,例如增加介面超時時間判斷,及時中斷呼叫,不要因為某個下游介面而影響整體效能,當下遊介面報錯時,也要做好異常捕獲,整體頁面可以直接丟棄這部分資料不做展示,而不能完全不展示。
  • 異常整體降級:在BFF閘道器內部處理邏輯中難免會有錯誤發生,或者下游核心的定位、商品等介面異常,這裡就需要做整體降級,例如模擬一個友情提示頁面等,提示使用者稍等重新重新整理,或者在未開通城市裡可以引導使用者切換地址,整體頁面的降級儘量交給BFF閘道器來做,而不要分散到不同的前端來做。

BFF閘道器劃分

bff4

介面粒度

如上圖,BFF閘道器的下游介面較多,如何聚合下游介面進行劃分是一個需要考慮的問題,這裡提供的建議是按照頁面來劃分,例如在首頁可以提供首頁介面返回整體展示效果,購物車頁面提供購物車介面,以頁面為單位劃分可以方便前後端的統一處理,當然如果頁面內容太多時,BFF閘道器介面可能耗時較多,可以同頁面拆分開來,讓前端並行載入介面,這樣既能降低整體頁面載入時間,也能讓BFF閘道器減少下游介面呼叫。

資料安全

BFF閘道器雖然也叫閘道器,但資料安全方面例如安全攻防等主要還是外層去做,BFF只負責資料的呼叫組裝,不要再賦予其他太多功能,但BFF閘道器一定要有限流邏輯,可以採用Sentinel等框架實現,防止某個前端異常進行大量請求,打垮BFF閘道器導致所有前端異常。

上線注意

BFF閘道器較為單薄,沒有依賴的資料庫等大型中介軟體,可能只是用到比較輕量的配置中心和訊息佇列,所以上線時初始化引數較少,但因為BFF閘道器需要做版本、定位、客戶端等特徵的資料處理,所以一定要做好灰度上線,防止新功能影響到歷史版本、不同定位下的使用者瀏覽。

優勢總結

  • 降低後端開發聯調成本:直接提供RPC介面將基礎資料返回即可;
  • 降低前端開發聯調成本:直接對接一兩個介面就可以拿到全部資料,並且可以將很多前端寫死的邏輯交給BFF閘道器做下發,提高前端展示的靈活性;
  • 方便需求迭代升級:當大量前端邏輯移植到BFF閘道器,很多需求的上線不再依賴前後端發版,直接讓BFF快速上線更新即可;
  • 提高使用者體驗:BFF閘道器可以較低成本的做異常降級處理,為前後端包裝錯誤提示,統一異常捕獲型別;
  • 提高系統效能:雖然引入BFF閘道器相當於多加了一層,但BFF閘道器可以透過併發呼叫下游介面,或者執行緒池的形式提高介面處理效能,而不需要像之前前端去逐個呼叫介面,規範了整體介面呼叫執行邏輯。

相關文章