BFF模式:微服務前端數據加載的最佳實踐?

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"設想一個場景,你需要使用微服務構建電子商務應用程序。你可以爲客戶、訂單、產品、購物車等提供微服務,微服務暴露 API 給前端使用。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但是,微服務提供給前端的數據可能不會按照前端需要的方式進行編排或過濾。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這種情況下,前端需要一些邏輯來重新處理這些數據,同時在用戶端使用這樣的邏輯會佔用更多的瀏覽器資源。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在這樣的情況下,我們可以使用 BFF 將一些前端邏輯轉移到中間層,中間層就是 BFF。當前端請求一些數據時,它將調用 BFF 中的 API。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"BFF 將執行以下操作:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"調用相關的微服務 API 並獲取所需數據"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"根據前端展現來處理數據"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"將格式化後的數據發送到前端"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因此,前端將有更少的邏輯,BFF 有助於簡化數據展示,併爲前端提供一個目的明確的接口。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"它如何適用於電子商務?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下圖顯示了每個微服務如何通過 BFF 與前端連接。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/wechat\/images\/d4\/d46ebd028ea8538548d75530918824dd.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":false,"pastePass":false}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"BFF 的角色"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"正如我們已經探討過的,BFF 充當前端和微服務之間的簡單接口。理想情況下,前端團隊也將負責管理 BFF。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一個 BFF 只關注一個 UI,而且只關注那個 UI。因此,它將幫助我們保持前端的簡單性,並通過後端輸出的統一的數據格式。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這就引出了下一個問題。我們能爲多個用戶界面提供多個 BFF 嗎?我們將在後面回答這個問題。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"這會增加延遲嗎?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在我們知道 BFF 類似於客戶端和其他外部 API、服務等之間的代理服務器。如果請求必須通過另一個組件,它肯定會增加延遲。但是,如果瀏覽器需要處理多個未針對前端優化的服務,那麼與瀏覽器的高資源使用率相比,BFF 延遲可以忽略不計。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"構建 BFF 允許你智能地對其他後端 \/ 微服務進行批處理調用,並一次返回所有數據,或者通過轉換和格式化數據來返回更方便的展現形式。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這對於 2G 或 3G 網絡上的移動客戶端非常有用,因爲在這些網絡上建立連接可能需要幾秒鐘(或更長時間)。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"應用程序何時使用 BFF"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"與許多其他模式一樣,在應用程序中使用 BFF 取決於你計劃遵循的上下文和體系結構。如果你的應用程序是一個簡單的單片應用程序(譯者注:"},{"type":"link","attrs":{"href":"https:\/\/www.zhihu.com\/question\/37905345\/answer\/75170829","title":"xxx","type":null},"content":[{"type":"text","text":"monolithic app"}]},{"type":"text","text":",單片軟件指非模塊化的軟件,也是一種設計思想。它將 UI、數據、邏輯等全部做成一整塊,以一個完全整體的方式實現,通常會直接從開始到結束完成一個複雜任務的每一小步,同時由自己獨立對所有的數據進行管理),那麼 BFF 是不必要的,它幾乎毫無價值。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但是,如果你的應用程序依賴於微服務,並且使用許多外部 API 和其他服務,那麼最好使用 BFF 來簡化數據流,併爲你的應用程序帶來更高的效率。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"此外,如果你的應用程序需要爲特定的前端接口開發優化的後端,或者你的客戶端需要使用在後端進行大量聚合的數據,那麼 BFF 是一個合適的選項。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"提示:分佈式設計需要不同種類的代碼協作工具。使用 Bit(Github)在單個組件上進行協作,這些組件可以跨代碼倉庫共享並獨立開發。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"保持你的代碼倉庫可擴展性、可維護性和始終同步。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"瞭解更多信息:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如何構建微前端:"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https:\/\/blog.bitsrc.io\/how-we-build-micro-front-ends-d3eeeac0acfc?fileGuid=S9EhcQ4jbascxSJk","title":"","type":null},"content":[{"type":"text","text":"https:\/\/blog.bitsrc.io\/how-we-build-micro-front-ends-d3eeeac0acfc?fileGuid=S9EhcQ4jbascxSJk"}]}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如何利用 Bit 在微服務間共享和重用代碼;"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https:\/\/blog.bitsrc.io\/how-we-successfully-share-and-reuse-code-between-microservices-at-scale-20fcfaebc6d0?fileGuid=S9EhcQ4jbascxSJk","title":"","type":null},"content":[{"type":"text","text":"https:\/\/blog.bitsrc.io\/how-we-successfully-share-and-reuse-code-between-microservices-at-scale-20fcfaebc6d0?fileGuid=S9EhcQ4jbascxSJk"}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"我們能有多個 BFF 嗎?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當然可以!這就是 BFF 的意義所在。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"沒有 BFF 的傳統應用程序對於各種客戶端只有一個 API 網關,如下所示,"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/wechat\/images\/a1\/a1acd9dc9240a084a52df5b549cbe202.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"來源:"},{"type":"link","attrs":{"href":"https:\/\/perspectives.mobilelive.ca\/","title":"","type":null},"content":[{"type":"text","text":"https:\/\/perspectives.mobilelive.ca\/"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"然而,擁有 BFF 的目的是爲客戶端提供一個可連接的集中接口。例如,移動 UI 的數據消耗可能不同於瀏覽器的數據消耗。在這種情況下,爲了更好地展示數據,可以使用兩個 BFF。多個 BFF 的應用程序如下圖所示,"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/wechat\/images\/01\/01adef90c2f9195b7e5351bea42a3d35.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"來源:"},{"type":"link","attrs":{"href":"https:\/\/perspectives.mobilelive.ca\/","title":"","type":null},"content":[{"type":"text","text":"https:\/\/perspectives.mobilelive.ca\/"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如你所見,每種客戶端都有一個 BFF,它將有助於優化服務(Sa、Sb…Sn)的響應。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"BFF 的優點"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"擁有 BFF 的幾個優點,"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"關注點分離"},{"type":"text","text":"——前端需求將與後端關注點分離,便於維護。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"更容易維護和修改 API"},{"type":"text","text":"——客戶端應用程序對 API 結構瞭解較少,這將使其對 API 中的更改更有彈性。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"更好的前端錯誤處理"},{"type":"text","text":"——大部分時間,服務器錯誤對前端用戶是沒有意義的。BFF 可以映射出需要顯示給用戶的錯誤,而不是直接返回服務器錯誤,這將改善用戶體驗。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"多種設備類型可以並行調用後端"},{"type":"text","text":"——當瀏覽器向 BFF 發出請求時,移動設備也可以這樣做。這將有助於更快地獲得相應服務的響應。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"更好的安全性"},{"type":"text","text":"——某些敏感信息可以被隱藏,並且在向前端返回響應時可以忽略不必要的數據。這種抽象將使攻擊者更難以應用程序爲目標。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"共享組件的團隊所有權"},{"type":"text","text":"——應用程序的不同部分可以由不同的團隊輕鬆處理。前端團隊可以共享客戶端應用程序及其底層資源消耗層的所有權,從而提高開發速度。下圖顯示了團隊劃分 BFF 的例子。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/wechat\/images\/b7\/b7eacd1fdc0d198530df6e613d1d54d2.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"來源:"},{"type":"link","attrs":{"href":"https:\/\/samnewman.io\/patterns\/architectural\/bff\/","title":"","type":null},"content":[{"type":"text","text":"https:\/\/samnewman.io\/patterns\/architectural\/bff\/"}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"在實踐中遵循的最佳實踐"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"到目前爲止,我們所看到的一切都是驚人的!但是,BFF 是否可以防故障?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"答案是否定的!和其他技術或模式一樣,即使是 BFF 也有陷阱。爲了避免這些,我們必須遵循一些最佳實踐。下面列出了一些要遵循的最佳做法。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"避免使用自包含的大而全的 API 實現 BFF"},{"type":"text","text":"——你的自包含 API 應該位於微服務層。大多數開發人員忘記了這一點,也開始在 BFF 中實現服務級別 API。你應該記住,BFF 是客戶端和服務之間的轉換層。當數據從服務端 API 返回時,其目的是將其轉換爲客戶端應用程序指定的數據類型。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"避免 BFF 邏輯重複"},{"type":"text","text":"——需要注意的一個關鍵點是,單個 BFF 應該滿足特定的用戶體驗,而不是設備類型。例如,大多數時候,所有移動設備(iOS、Android 等)共享相同的用戶體驗。在這種情況下,所有這些操作系統的一個 BFF 就足夠了。iOS 不需要單獨的 BFF,Android 也不需要單獨的 BFF。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"避免過度依賴 BFF"},{"type":"text","text":"——BFF 只是一個轉換層。是的,它也爲應用程序提供了一定程度的安全性。但是,你不應該過分依賴它。你的 API 層和前端層應該負責所有的功能和安全方面,而不管是否存在 BFF。因爲 BFF 只是填補一個空白,而不是嚮應用程序添加任何功能或服務。"}]}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"總結"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"BFF 模式不僅有助於開發,而且有助於極大地改善用戶體驗。因此,在保持 BFF 專注於其前端的同時,考慮數據優化和聚合是非常重要的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"此外,如果你以前沒有使用過 BFF 模式,現在是時候開始了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"延伸閱讀"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https:\/\/blog.bitsrc.io\/bff-pattern-backend-for-frontend-an-introduction-e4fa965128bf","title":"","type":null},"content":[{"type":"text","text":"https:\/\/blog.bitsrc.io\/bff-pattern-backend-for-frontend-an-introduction-e4fa965128bf"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章