想象下当你使用微服务去搭建一个电子商务应用。你可能会有客户、订单、产品、购物车等微服务。微服务暴露 API 给前端调用。
但是,微服务返回给前端的数据可能不会根据前端需要表示它们的确切方式进行格式化或者过滤。
在这种情况下,前端需要有一些自己的逻辑去重新格式化这些数据。在前端有这些逻辑会占用更多的浏览器资源。
像这种情况,我们可以使用 BFF 将一些前端逻辑转移到中间层。这个中间层就是 BFF。当前端请求一些数据时,它会调用 BFF 的 API。
BFF 会做以下事情:
- 调用相关微服务的 API 并获取所需的数据
- 基于前端的表示去格式化数据
- 发送格式化后的数据给前端
这样之后,前端将保留更少的逻辑。因此,BFF 有助于简化数据表示,并负责给前端提供重点突出的接口。
💡另一个简化前后端关系的方式是在它们之间共享类型。学习如何使用 Bit 在解耦项目之间共享类型(或者其他代码):Sharing Types Between Your Frontend and Backend Applications
如果你乐意去看:
在电子商务应用例子中如何使用 BFF?
下面这张示意图展示了各个微服务是怎么通过 BFF 和前端连接起来的:
BFF 的角色
正如我们所探索过的,BFF 在前端和微服务间充当简单的接口。理想情况下,前端团队也应该要负责管理 BFF。
单个 BFF 专注于单个 UI,并只专注此 UI。因此,它有助于保持前端逻辑的简单,通过其后端可以查看到数据的统一视图。
这就引出了下一个问题。我们可以为多个 UI 有多个 BFF 吗?我们将在这篇文档的后面章节回答这个问题。请继续看下去。😊
这会增加延迟吗?
现在我们知道 BFF 有点类似于客户端和其他外部 API、服务等之间的代理服务器。如果请求需要经过另一个组件,这必定会带来延迟。但是,如果需要使用多个未针对前端优化的服务来说,BFF 的延迟相较于浏览器的高资源使用相比可以忽略不计。
搭建 BFF 可以智能的批量调用其他后端/微服务,并一次返回所有数据,或者通过转换和格式化数据返回更方便的表示。
这对于 2G 或 3G 网络中的移动客户端非常有用,因为这些客户端可能需要几秒(或者更长时间)才能建立连接。
什么时候为你的应用使用 BFF?
与许多其他模式一样,是否在应用中使用 BFF 取决于上下文和你计划去遵循的架构。例如,你的应用是一个简单的单体应用,则 BFF 是不必要的,它几乎没有任何价值。
但是,如果你的应用依赖微服务并且消费多个外部 API 和其他服务,那么最好使用 BFF 去简化数据流并可以为你的应用引入大量效率。
此外,如果你的应用需要为特定的前端接口开发优化的后端,或者客户端需要使用需要在后端进行大量聚合的数据,那么 BFF 会是个合适的选项。
可以有多个 BFF 吗?
当然可以!这就是有 BFF 的意义。
传统方式(没有 BFF 的应用)对于所有客户端只有一个 API 网关。看起来是这样的。
但是,BFF 的目的是为了提供客户端集中的接口去连接。例如,移动端 UI 的数据消费和浏览器的数据消费是不同的。在这个例子中,为了更好的数据表示,可以使用两个 BFF。
让我们看下一个拥有多个 BFF 的应用示意图:
可以看到每个客户端都有一个 BFF。这有助于优化服务端的响应。
BFF 的好处
下面列出了一些 BFF 的好处:
- 关注点分离 —— 前端需求将与后端关注点分开。这更易于维护。
- 更易于维护和修改 API —— 客户端应用更少关注 API 的结构,这将使其更能适应这些 API 的变化。
- 在前端更好的处理错误 —— 服务端错误对于前端用户来说大多数时候是无意义的。和直接返回服务端的错误相比,BFF 可以映射出需要展示给用户的错误。这可以提升用户的体验。
- 多种设备类型可以并行调用后端 —— 当浏览器在向浏览器 BFF 发起请求时,移动端设备同样可以发起。这有助于从服务端获得更快的响应。
- 更好的安全性 —— 当返回数据给前端时,某些敏感的信息可以被隐藏,对于前端来说不必要的数据也可以省略掉。抽象将使得攻击者更难瞄准应用。
- 共享团队对组件的所有权 —— 应用中的不同部分可以由不同团队轻松的处理。前端团队可以享受其客户端应用和底层资源消耗层的所有权;使得可以高效开发。下图展示了使用 BFF 后团队分离的例子。
实践中应遵循的最佳做法
到目前为止我们看到的是多么令人惊讶!但是,BFF 是防错的吗?
答案是:不!像其他每一种技术或者模式一样,BFF 是有陷阱的。为了避免,我们要去遵循最佳实践。
- 避免使用完全独立且包含所有必要功能的 API 来实现 BFF —— 完全独立的 API 应该在微服务层。许多开发者会忘记这点并开始在 BFF 开发服务级别的 API。 BFF 是客户端和服务端的转换层,这点需要牢记于心。当数据从服务端 API 返回时,BFF 的目的是把数据转换为客户端应用指定的数据类型。
- 避免 BFF 逻辑重复 —— 需要注意的关键一点是单个 BFF 应该考虑特定的用户体验,而不是设备类型。例如,大多数时候,所有移动设备(iOS,安卓等)有同样的用户体验。在这种情况下,一个 BFF 对于这些操作系统是足够的。不需要为了 iOS 和安卓使用不同的 BFF。
- 避免过度依赖 BFF —— BFF 仅仅是一个转换层。当然,它为应用程序提供了一定程度上的安全。但是你也不应该过度依赖它。无论是否存在 BFF,你的 API 层和前端层应该关心所有功能和安全方面。因为 BFF 的目的是为了填补空白,不是为了给应用添加功能或者服务。
- 要为你的微服务实现更易于管理的 BFF 模式,一个好的做法是将每个 BFF 都视作组件,然后为它们利用模块化、可重用和可共享的方法。为了这个,你可以再次使用 Bit 将每个组件视为单独的包去创建,发版,发布和共享 —— 甚至使用 Bit 的 variants 为每个创建不同的配置。
总结
BFF 模式不仅仅帮助了开发,同时也有利于提升用户体验。因此,必须考虑数据优化和聚合,同时让 BFF 专注于前端。
此外,如果你之前没有使用过 BFF 模式,那么现在是时候去使用了。
这里有一些工具可用于实现 BFF 模式: