BFF

Backend for Frontend 是一种模式,在构建 API 时当然可以不选择使用 BFF,取而代之的是对多个 UI 终端提供一个统一的 API,但是不可避免的会带来一些问题:

  1. 不同的 UI 终端展示的数据是不一样的,比如 Web H5 和 App 之间会存在较大的差异
  2. 不同的 UI 终端可能会有不同的逻辑,比如有些数据是 Web 用,有些则是 App 用,这样都放在一个接口里的话,对不同的终端来说,都会有一些无用的数据,或者是无用的逻辑,这样会导致接口的复杂度增加,维护成本增加;从节约流量和资源的角度说,移动端应该尽可能少的去拉取数据
  3. 统一的 API 在开发新功能时,可能会对不同 UI 终端都产生影响,而且功能逻辑会相互耦合;也就是说一个接口承担了更多的职责

总结来看:由于不同终端的差异性,导致对后端 API 的数据产生了不同的需求,驱动我们去考虑针对不同的 UI 来定制不同的接口。

通用的 API 后端和团队组成如下

通用 API 后端 通用 API 后端 通用 API 团队组成 通用 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 Overview BFF Overview

  1. BFF 的接口通常是由前端开发人员来定义,由后端开发人员来实现
  2. BFF API 一般以 UI 为依据,这样更集中
  3. 至于是不是必须为每个类型的终端都定义不同的 BFF,这个需要根据实际情况来判断,或者团队来决定采用何种模式;比如 iOS 和 Android 的 UI 体验几乎完全一致,我们有必要指提供一套 BFF,而不是一个 iOS BFF 和一个 Android BFF;所以具体情况还要具体分析,没有一个标准答案
  4. 在调用多个下游服务时,使用 RxJava 或 Finagle 这类响应式编程风格的方式会更加的易于管理,而且可以更好的控制并发度,提高性能
  5. 在使用 BFF 时带来的最大困扰是重复代码,这个可能无法避免,但是在合理的情况下可以考虑复用代码、抽象代码达到消除重复的目的
  6. 一个指导规则可能是:如果被提取的功能不必同时更新,则使用共享库,但如果需要,则使用服务。
  7. 谈论复制和重用,不要试图从一开始就让一切通用。如果你尝试,并且它在整个组织中使用,就会引起摩擦,因为很多人都想做出贡献。在考虑通用用法之前,请专注于您的功能和特定用例。“特殊功能优先于通用用法”策略效果更好。在考虑提取代码时,不要忘记有用的“三法则”。

关于 BFF 的实践可以看一下 BFF @ SoundCloud 这篇文章,里面有一些很好的实践经验。

什么时候用 BFF ? 当你有多个微服务,并且需要应对不同的 UI 终端,而且这些终端之间存在差异性,可以考虑使用 BFF 模式。

Event-driven BFF

AWS 提出了一个 event-driven BFF 的东西: Backends for Frontends Pattern by AWS

AWS event driven BFF AWS event driven BFF

  • 右边是微服务或单体服务发出的 event,这些 event 在 Domain 发生更新时发出
  • 中间是 Event bus,接收 event 后转发给左边的 BFF 层的订阅者
  • 左边是 BFF 的实现,不同的 BFF 可以有不同的数据库投影,根据具体的需求来定制数据结构,当然也可以支持 CDC 模式

还有一种更加云原生的方式来构建服务

AWS event driven BFF AWS event driven BFF

Reference