yuff100

V1

2022/12/31阅读:15主题:极简黑

5分钟搞懂BFF

随着微服务架构越来越复杂,前端需要和越来越多的后端服务交互,为了解决前端的复杂性问题,提出了BFF架构。原文: What is a BFF? And how to build one?

现在谁还会构建单体服务?微服务才是正确的选择!但这不是一个容易的选择,会引入各种各样复杂性。比方说,假设后端有若干对前端隐藏的微服务,那对于SPA或移动应用来说会产生多少额外的开销?

通用API可能会要求使用者聚合、过滤各个端点的响应,以便为终端用户提供有用的内容。

如何维护由多个微前端连接的一系列微服务架构?微服务承诺让应用更加敏捷,可以随意创建新的微服务,并在需要时拆除旧的服务,但这将对前端产生什么样的影响?

因此,为了解决这些问题,现在出现了另一种模式: The Backend For Frontend。这一概念正如所期望的那样: 每个前端都有一个后端,充当前端应用程序(SPA/Mobile)和域服务之间的接口,是一个用于查询下游服务并将响应转换为专门针对特定前端的单一格式化响应的API。从示意图上看,微服务环境中的BFF可能是这样的:

BFF+微服务架构
BFF+微服务架构

BFF的概念最早是由SoundCloud提出[1]的。

BFF,身份验证,以及无cookie时代

你可能想知道这与本文有什么关系,在没有cookie的时代,BFF模式比上图中显示的要复杂一些。

在许多情况下,下游服务通常需要基于(访问)令牌验证身份,BFF需要在向下游转发的请求中包含这些令牌。

在SPA中存储access_token是一种常见的实践。令牌被包含在请求中,API就能够知道是谁在执行请求。但是通常来说,这种方法会有一个问题。当令牌过期(通常是一小时),SPA一般会静默刷新令牌。这种机制是基于第三方cookie的,而这些cookie很快就没法再用[2]了。因此,2024年以后就没法再用静默刷新。

考虑到这一点,BFF无论如何都需要用户的access_token,这使得对SPA进行身份验证成了一件怪事。对于BFF, SPA不应该直接与下游服务通信,然而因为需要身份验证,BFF总是需要在下游请求中包含access_token。因此,从这个角度来看,让最终用户只针对BFF进行身份验证更有意义。这消除了通过SPA更新令牌的需要(并且根本不需要在SPA中拥有令牌)。

下图展示了BFF和微服务的身份验证过程:

BFF认证时序图
BFF认证时序图

要使其工作,BFF和SPA必须托管在相同的URL上,这样,当SPA向BFF发起HTTP请求时,HTTP请求将包含cookie,而BFF需要通过这些cookie来获取用户上下文(access_token)并将其转发到下游。

如何实现?

BFF是前端的一部分,减少了对下游服务的API请求数量,并减少了前端到BFF之间传输的数据量。BFF通过转换API请求并转发到一个或多个通用API来实现这一点,同时支持聚合响应并将其转换为仅包含前端所需内容的响应。

这仍然是一个相当宽泛的定义,应该如何实现呢?Cam Jackson给出了一个更复杂的定义:

图片来源: https://martinfowler.com/articles/micro-frontends.html
图片来源: https://martinfowler.com/articles/micro-frontends.html

根据这一定义,有几种方法符合要求,分别支持带有专用存储的成熟API服务以及能够转发请求并在需要时转换响应的第三方实现。

选择1: Duende

不必自己实现,有几个项目提供了免费的现成解决方案。例如,IdentityServer的维护者提供名为Duende的解决方案: https://docs.duendesoftware.com/identityserver/v5/bff (实现示例如下:https://docs.duendesoftware.com/identityserver/v5/samples/bff)

通过将Duende纳入项目,可以作为一个很好的开始。它实现了身份验证机制,并且可以配置为将请求转发到下游API。

选择2: 自己实现

考虑到BFF的非泛型性质,自己构建是有意义的。你需要做以下事情:

  • 创建一个API项目。
  • 实现身份验证,使用OpenId连接授权代码流(基于PKCE)并将访问令牌存储在安全cookie中。
  • 创建API端点并从cookie中获取令牌,用令牌调用要使用的服务的端点。
  • 必要时转换响应。
  • 创建SPA并将其托管在同一个站点/项目上。
  • 通过前面创建的API端点发布SPI。
  • 就这些……

总结

微服务和微前端之间的通信可能并不高效,微服务可能提供了通用API(如果有的话),所以前端可能需要调用多个微服务来完成工作,并从响应中过滤需要显示的信息。结果,前端变得很复杂。

此外,当服务变得更小时,就需要调用更多的服务来完成工作。多个前端都需要调用所有这些对象的方式可能并不可取,使得维护更加困难。

为了解决这些问题,SoundCloud在架构中引入了一个额外的层,将API作为前端的一部分,充当前端和下游服务之间的接口,聚合响应或/和过滤有效响应。

这个概念就被称为BFF(Backend For Frontend)。


你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。
微信公众号:DeepNoMind

参考资料

[1]

The Back-end for Front-end Pattern: https://philcalcado.com/2015/09/18/the_back_end_for_front_end_pattern_bff.html

[2]

Google ending third-party cookies in Chrome: https://www.cookiebot.com/en/google-third-party-cookies

- END -

分类:

后端

标签:

后端

作者介绍

yuff100
V1

俞凡,公众号DeepNoMind