引言
晚上公司開了一個技術分享會,主要內容就是公司的專案架構,會中講解了專案整體架構是BFF
架構,就是在微服務之上多加了一層。
除此之外,還講解了DDD
設計思想,主要用於各個業務中臺,如訂單中臺、使用者中臺等。
這是我的架構第一課,聽得有些似懂非懂,於是淺淺地整理一下。
BFF
是什麼
BFF
是服務於前端的後端,全稱Backend For Frontend。BFF
的位置在與客戶端與服務端中間,起到一箇中介軟體的作用,我在聽的過程中更覺得像是一個前端與後端之間的閘道器。
為什麼使用
BFF
是近些年新衍生出來的一種開發模式,或者說是一種適配模式的系統,為了適配微服務模式下前端後端系統介面呼叫混亂而出現的。
在如今微服務盛行的趨勢下,大型系統中劃分出了數十個服務模組,例如商品,門店,運費,紅包,訂單,優惠券,CMS,使用者,搜尋,推薦,廣告等等系統,前端也有小程式,APP,網頁等端。由此產生了很多問題:
- 前端問題:每次需求開發前端要對接多個系統來確認介面資訊,不同的資料要找不同的系統,各個介面散落一地,開發除錯的效率極低。
- 後端問題:後端同樣也需要各自包裝資料資訊來提供前端處理,重心變成如何為前端提供資料,因為需要根據不同的版本、客戶端、使用者、定位等特徵來判別,很多時間浪費在展示層,而不能專注於業務邏輯處理,每個後端系統各自為戰,都有自己的介面規則,各種歷史版本問題都不能完全統一,所有系統都嚴重耦合了版本問題。
- 變更不靈活:當產品想要更新需求時,更是牽一髮而動全身,某一塊的小改動需要在各個系統之間找介面來回溝通,大部分系統都要重新上線一次。
如下圖所示,未啟用BFF
架構之前,前後端的溝通鏈路過多。
BFF的閘道器定位
鑑於以上痛點,需要一箇中間層來適配前後端服務,BFF
由此而生,它負責將所有下游後端介面進行統一呼叫,下游介面只需要提供RPC
介面供閘道器使用,BFF
閘道器提供Web介面來讓前端呼叫,最後將資料進行組裝拼接,根據前端的需求來返回資料。
所以BFF
的核心定位就是:“統一下游介面,為前端提供服務”。
只有把握好服務這個概念,才能做好BFF
閘道器係統,其他系統可以扯皮甩鍋,但BFF
閘道器不可以,它與生俱來的使命就是把這兩邊拉扯起來,所有不合理不合適,繁瑣無用的邏輯都需要BFF
閘道器去處理,後端只要做好業務邏輯,前端做好展示,其他的都可以交給BFF
閘道器。
BFF閘道器特點
BFF
作為一種特殊閘道器,還有以下特點:
瑣碎
BFF
閘道器主要為前端進行服務,前端不關心版本、客戶端、定位、使用者身份等情況,只接收渲染資料即可,而這些邏輯都需要耦合到BFF
閘道器中,以版本、客戶端、定位、使用者等特徵作為緯度,其中版本最為最複雜的分支,可能貫徹整個系統生涯幾十個版本型別都需要做相容,由此還需要兼顧不同客戶端的展示要求和使用者特徵,所以BFF
閘道器中必然需要做大量判斷分支,根據上百種情況組合判斷來生成-唯一版本-唯一端-唯一使用者的資料結構。
資料瑣碎
BFF
不需要資料庫,這點會在下面說明,所以有很多資料需要以靜態變數的形式存放在程式碼裡,或者是使用配置中心來動態配置,例如圖片地址、各種色值、模組固定文字、處理標識等,這些瑣碎的資料都會存放在BFF
閘道器中進行維護,如果放在前端,修改時必須要進行發版,時間週期太長,而存放在後端的話,又會打散資料,不能從一個地方作為主要資料視窗進行管理。
邏輯瑣碎
衍生第一點說到的,BFF
閘道器作為下游介面的聚合,每次流程需要呼叫數十個後端介面,再根據版本、端、使用者進行邏輯處理,歷史邏輯與新需求雜糅在一起,實現新功能的同時要不斷兼顧歷史邏輯,只能是加入大量的分支判斷,最後變成了if大爆炸,或者使用策略模式進行最佳化,但無論如何怎麼包裝都無法掩蓋瑣碎的邏輯。
效能
BFF
閘道器的耗時主要有兩部分:
- 內部處理耗時
- 下游RPC介面耗時
BFF
作為最直接和前端互動的介面,BFF
的耗時將直接影響使用者瀏覽體驗,所以BFF
效能一定要最優,不斷壓縮耗時來提高介面響應效能,內部邏輯最佳化時,首先觀察下游介面耗時情況,各個模組之間難免重複呼叫介面,可以使用編排框架將下游介面呼叫進行最佳化。然後使用執行緒池進行併發處理,能夠併發處理的一定要併發執行,這樣可以極大降低下游介面耗時,提供介面處理能力。
快取
切勿在
BFF
閘道器中使用快取
此處指的快取主要是Redis
等中介軟體快取,BFF
閘道器主要資料來源都是透過呼叫下游介面獲取,這裡是最耗時的,如果想要減少下游介面耗時,應該使用併發或者編排能力,而不可以透過快取下游介面資料來實現。
- 成本問題:下游介面資料會根據傳入的定位、使用者等資訊查詢,當系統使用者量大、覆蓋城市多時,需要快取的資料量將劇增,而資料快取後再次訪問機率很低,造成嚴重的快取空間浪費。
- 一致性問題:
BFF
閘道器的引入主要是為了統一後端介面,效能是閘道器的一大指標,但不能為了效能將所有下游介面資料進行快取,從而犧牲資料一致性,後續展示時一旦出現問題,將增加排查難度。
降級
任何時候都不要將錯誤直接返回給使用者,不論是下游的錯誤還是系統內部的錯誤,這一點完全可以交給BFF
閘道器來做,這裡降級可以分為兩型別處理。
- 下游介面降級:當下遊介面出現超時或資料異常時,一定要做好降級措施,例如增加介面超時時間判斷,及時中斷呼叫,不要因為某個下游介面而影響整體效能,當下遊介面報錯時,也要做好異常捕獲,整體頁面可以直接丟棄這部分資料不做展示,而不能完全不展示。
- 異常整體降級:在
BFF
閘道器內部處理邏輯中難免會有錯誤發生,或者下游核心的定位、商品等介面異常,這裡就需要做整體降級,例如模擬一個友情提示頁面等,提示使用者稍等重新重新整理,或者在未開通城市裡可以引導使用者切換地址,整體頁面的降級儘量交給BFF閘道器來做,而不要分散到不同的前端來做。
BFF閘道器劃分
介面粒度
如上圖,BFF
閘道器的下游介面較多,如何聚合下游介面進行劃分是一個需要考慮的問題,這裡提供的建議是按照頁面來劃分,例如在首頁可以提供首頁介面返回整體展示效果,購物車頁面提供購物車介面,以頁面為單位劃分可以方便前後端的統一處理,當然如果頁面內容太多時,BFF
閘道器介面可能耗時較多,可以同頁面拆分開來,讓前端並行載入介面,這樣既能降低整體頁面載入時間,也能讓BFF
閘道器減少下游介面呼叫。
資料安全
BFF
閘道器雖然也叫閘道器,但資料安全方面例如安全攻防等主要還是外層去做,BFF
只負責資料的呼叫組裝,不要再賦予其他太多功能,但BFF
閘道器一定要有限流邏輯,可以採用Sentinel
等框架實現,防止某個前端異常進行大量請求,打垮BFF
閘道器導致所有前端異常。
上線注意
BFF
閘道器較為單薄,沒有依賴的資料庫等大型中介軟體,可能只是用到比較輕量的配置中心和訊息佇列,所以上線時初始化引數較少,但因為BFF
閘道器需要做版本、定位、客戶端等特徵的資料處理,所以一定要做好灰度上線,防止新功能影響到歷史版本、不同定位下的使用者瀏覽。
優勢總結
- 降低後端開發聯調成本:直接提供
RPC
介面將基礎資料返回即可; - 降低前端開發聯調成本:直接對接一兩個介面就可以拿到全部資料,並且可以將很多前端寫死的邏輯交給
BFF
閘道器做下發,提高前端展示的靈活性; - 方便需求迭代升級:當大量前端邏輯移植到
BFF
閘道器,很多需求的上線不再依賴前後端發版,直接讓BFF
快速上線更新即可; - 提高使用者體驗:
BFF
閘道器可以較低成本的做異常降級處理,為前後端包裝錯誤提示,統一異常捕獲型別; - 提高系統效能:雖然引入
BFF
閘道器相當於多加了一層,但BFF
閘道器可以透過併發呼叫下游介面,或者執行緒池的形式提高介面處理效能,而不需要像之前前端去逐個呼叫介面,規範了整體介面呼叫執行邏輯。