前端架构设计文档基于react 前端架构bff_前端架构设计文档基于react

前言

上一篇介绍了BFF相关的5个使用案例。本篇将结合笔者在实际项目中多次采用BFF的经验来说明反模式出现的原因和相应的解决方法。

BFF 是一种架构模式,但并不是任何情况都适用。如果对它的优缺点了解不够透彻,就冒然采用的话,你可能会后悔。我在实际项目中多次采用了BFF,但并非所有项目都很成功。相反,由于引入的新的东西,从而产生了一些新的问题,而且责任范围的改变也造成了一些项目上的失误。

因此,这一篇,我将根据我的经验介绍以下三种BFF反模式。反模式名称是我自己取的,是为了方便起见,命名如下:

  • 导致沟通不畅的“稀疏沟通”
  • BFF处理过度的“Fat Front”
  • 最后阶段一次性发布的“Big Bang Joint”

反模式的原因通常是组织的问题和沟通的问题,当然我也会介绍如何避免这些问题。

【反模式1】导致缺乏沟通的“稀疏沟通”

由于使架构松散耦合(Sparse),沟通也变得“稀疏”的现象称为“稀疏沟通”。造成这种现象的原因包括不重视“报告、联系、咨询”和“因组织不同造成的沟通成本”。

BFF使得架构保持松散耦合,并不意味着前端工程师和后端工程师之间的沟通就可以忽略不计。在很多情况下,没有哪一个系统不需要沟通就可以创建。

加强对API的共同理解,并同时开发前端和后端

直接避免稀疏沟通的唯一方法是“沟通”。另一方面,可以通过技术减少对 API 认知差异。

一种做法是将前端和后端的代码放到同一个仓库,同时将基于“Swagger”或“Agreed”的API规格和源代码一起管理。当更改 API 规格时,也会提交PULL REQUEST请求,这样可以将API的变更通到给整个开发团队。

消费者驱动合约(Consumer Driven Contract)

作为另一种解决方法,可以先在后端确定好了 API 规格之后,前端再开始实现。这样做认知偏差发生的可能性较小,但前端的实现速度较慢。

因此,Recruit 正在研究一种称为“Consumer Driven Contract”的方法,以同时进行前端和后端的开发,并减少 API 的认知差异。

Consumer Driven Contract是前端主动决定API规格的一种方式。更多细节可以在“Consumer-Driven Contracts: A Service Evolution Pattern”中找到。

前端架构设计文档基于react 前端架构bff_java_02

在常规方法中,后端即上图中的“Provider”定义API规格,前端即“Consumer”相应地创建客户端。具体来说,利用Recruit 开发的“Agreeed”,前端将率先决定API规格如下。

前端架构设计文档基于react 前端架构bff_java_03

首先描述前端要发送的HTTP Request和要接收的HTTP Response的定义,称为“契约(Contract)”。之后,根据这个契约创建一个 API 模拟服务器。

经过一段时间的开发后,该契约可以成为测试后端的 API 客户端。

前端架构设计文档基于react 前端架构bff_java_04

 

这样做,消费者和提供者都可以在减少 API 认知差异方面发挥作用。如果后端更改实现或前端更改 API 规格,则更改将以 Agreed 为中心传播。通过让后端测试失败或前端代码不工作,使得彼此对更改变得敏感,可以减少认知差异。

当然,漏洞很多,所以即使你采取了这个方法,交流也是必不可少的。

详情请参考《[Recruit Technologies Frontend Development 2016](yosuke-furukawa.hatenablog.com/entry/2016/…

【反模式2】BFF处理过度的“Fat Front”

前面系列已经讲过,通过设置BFF服务器,可以将各种处理转移到BFF上,不需要在后端管理会话等。但是,BFF 只是用于在前端创建网页和用户界面 (UI) 的服务器。如果从后端转移过来的处理过多,BFF的负载就会增加,从而导致整个服务的性能下降。

这种情况被称为“胖前端(Fat Front)”。

说到实际的问题,BFF出现了所谓的“N+1问题”的现象。用于搜索之类的列表查询的API过于简单,在一个处理中无法获取页面显示所需的信息,而是分割成两个处理:“列表查询(只列出ID)”和“详细信息查询(从id获取其他属性)”。结果,我们不得不发出多个请求。

情况如下。创建用户列表画面时,搜索“/users”,此时以JSON形式返回ID列表。

前端架构设计文档基于react 前端架构bff_前端架构设计文档基于react_05

 

接下来出现了这样的一个现象,按照ID的数量发起“/users/{id}”请求,每次获取一个ID的详细信息。

前端架构设计文档基于react 前端架构bff_微服务_06

 

这样一来,即使 API 可以高效并行执行,BFF 和从后端获取信息也会花费太多时间。理想情况下,如果从一开始就将详细信息包含在列表信息中,则可以通过单个 API 请求获取所需的信息,并且不会导致 BFF 过载。

明确 BFF 和后端职责

当BFF和后端的责任不明确,理解不够时,就会出现胖前端。

再一次强调,BFF是UI的服务器,主要作用是“显示”相关的处理。另一方面,后端主要负责提供独立于 UI 的“核心”功能,称为“领域逻辑”或“业务逻辑”。要想预防胖前端,首先这个共识很重要。

如果你觉得BFF处理在增加,你应该停下来考虑一下是否可以改变后端API。

【反模式3】 最后阶段一次性发布的“Big Bang Joint”

不限于BFF,在并行开发API和前端时,尽可能减少相互认知的差异很重要。因此,我介绍了Consumer Driven Contract方法和将API规格放到同一个代码仓库的方法。但是,无论如何努力,始终存在认知差异和BUG等不确定性。

发生这些并不是坏事。问题在于,不考虑这些不确定性,而在临近发布时,才将BFF和后端结合到一起。

留有余地很重要,要小心“突然的结合导致系统停滞”。

逐步结合BFF和后端

在我的团队中,我尝试在固定时间一点点地与后端结合,而不是突然结合。未实现的 API 使用 Mock ,并逐渐增加已实现的后端的比例。

前端架构设计文档基于react 前端架构bff_微服务_07

 

此外,在逐步连接到真实后端的过程中,我们可以尽早发现不一致和错误。但是,前端还没有实现的部分是无法在页面上确认的。这部分的确认会延迟,当出现差异或错误时,需要考虑到这一点,同时最好从可能存在较多返工的部分优先开始着手。

即使采用逐步结合的模式,BFF和后端的结合也需要时间。所以建议充分预留缓冲时间。

组织问题与架构设计之间有着密切的关系

上面介绍了三种BFF反模式以及如何避免,感觉如何?

许多反模式根源于组织问题。首先,BFF 和微服务是根据组织的形态而演进出来的架构。组织面临的挑战与架构设计之间有着密切的关系。

架构本身并不能直接解决组织的问题。为了让组织的问题更好解决,需要采取“沟通”、“加深对BFF和后端的了解”、“制定时间表和工作开展方式”等方法。

如果你误以为“引入BFF可以解决组织问题,提高开发效率”,并不假思索地采用,那就解决不了问题。

前端开发的未来

最后,我将总结到目前为止在该系列中所讲的内容,并在可预测的范围内谈谈基于 BFF 的前端开发的未来。

BFF模式的产生是由于微服务的架构,一些服务于前端的功能被转移到特定服务器。在实践中,前端工程师不仅需要关注浏览器的行为,还需要对CPU和内存、调优、HTTP协议等服务器端资源监控有深入的了解。

前端工程师和后端工程师有分工,但也有很多需要共享的知识。前端工程师不能“因为BFF是服务器”而对BFF监控和调优无动于衷。另一方面,后端工程师也不应该回避说“BFF不是我的开发,前端代码不熟悉”。提高服务质量这一点上,前端和后端是相同的,都必须面对。

不知道未来BFF会不会成为前端和后端之间的桥梁,或者BFF本身的概念是否会被废除。从“技术在反复回旋中进步”的流程来看,可以想象,曾经因微服务而偏向松耦合的架构,将再次回归紧耦合。 从这个角度来看,与其说未来“前端与后端的距离在拉大”,倒不如说是“在靠近”。 为此,前端和后端都必须毫不犹豫地接受彼此领域的知识。

BFF架构模式是一种充当前端和后端之间桥梁的技术,我认为它是一种符合当前趋势的架构