BFF
Backend for Frontend 是一种模式,在构建 API 时当然可以不选择使用 BFF,取而代之的是对多个 UI 终端提供一个统一的 API,但是不可避免的会带来一些问题:
- 不同的 UI 终端展示的数据是不一样的,比如 Web H5 和 App 之间会存在较大的差异
- 不同的 UI 终端可能会有不同的逻辑,比如有些数据是 Web 用,有些则是 App 用,这样都放在一个接口里的话,对不同的终端来说,都会有一些无用的数据,或者是无用的逻辑,这样会导致接口的复杂度增加,维护成本增加;从节约流量和资源的角度说,移动端应该尽可能少的去拉取数据
- 统一的 API 在开发新功能时,可能会对不同 UI 终端都产生影响,而且功能逻辑会相互耦合;也就是说一个接口承担了更多的职责
总结来看:由于不同终端的差异性,导致对后端 API 的数据产生了不同的需求,驱动我们去考虑针对不同的 UI 来定制不同的接口。
通用的 API 后端和团队组成如下
使用 BFF
The goal of the BFF pattern is to decouple the front-end applications from the back-end services and to reuse the APIs while ensuring that it doesn’t cause over-fetching or over-requesting on the client-side. This is accomplished by developing a dedicated back-end for each front-end service. The BFF transforms the data into the correct format that the client application needs.
- BFF 的接口通常是由前端开发人员来定义,由后端开发人员来实现
- BFF API 一般以 UI 为依据,这样更集中
- 至于是不是必须为每个类型的终端都定义不同的 BFF,这个需要根据实际情况来判断,或者团队来决定采用何种模式;比如 iOS 和 Android 的 UI 体验几乎完全一致,我们有必要指提供一套 BFF,而不是一个 iOS BFF 和一个 Android BFF;所以具体情况还要具体分析,没有一个标准答案
- 在调用多个下游服务时,使用 RxJava 或 Finagle 这类响应式编程风格的方式会更加的易于管理,而且可以更好的控制并发度,提高性能
- 在使用 BFF 时带来的最大困扰是重复代码,这个可能无法避免,但是在合理的情况下可以考虑复用代码、抽象代码达到消除重复的目的
- 一个指导规则可能是:如果被提取的功能不必同时更新,则使用共享库,但如果需要,则使用服务。
- 谈论复制和重用,不要试图从一开始就让一切通用。如果你尝试,并且它在整个组织中使用,就会引起摩擦,因为很多人都想做出贡献。在考虑通用用法之前,请专注于您的功能和特定用例。“特殊功能优先于通用用法”策略效果更好。在考虑提取代码时,不要忘记有用的“三法则”。
关于 BFF 的实践可以看一下 BFF @ SoundCloud 这篇文章,里面有一些很好的实践经验。
什么时候用 BFF ? 当你有多个微服务,并且需要应对不同的 UI 终端,而且这些终端之间存在差异性,可以考虑使用 BFF 模式。
Event-driven BFF
AWS 提出了一个 event-driven BFF 的东西: Backends for Frontends Pattern by AWS
- 右边是微服务或单体服务发出的 event,这些 event 在 Domain 发生更新时发出
- 中间是 Event bus,接收 event 后转发给左边的 BFF 层的订阅者
- 左边是 BFF 的实现,不同的 BFF 可以有不同的数据库投影,根据具体的需求来定制数据结构,当然也可以支持 CDC 模式
还有一种更加云原生的方式来构建服务
Reference
- Pattern: Backends For Frontends - Sam Newman 写的关于 BFF 模式的文章
- BFF 架构简介
- BFF @ SoundCloud
- A Deep Dive into the Back-End for Front-End Pattern
- Backends for Frontends Pattern
- Seamlessly Swapping the API backend of the Netflix Android app - Netflix Android App 的 BFF 实践
- Backend for frontend (BFF) pattern— why do you need to know it?
- Backends for Frontends pattern by Azure