写点什么

BFF 治理与优化实践

作者:码猿外
  • 2022 年 4 月 06 日
  • 本文字数:2941 字

    阅读完需:约 10 分钟

BFF治理与优化实践

原文连接:https://maguangguang.xyz/bff-governance


在 Thoughtworks 的第 25 期 技术雷达 中有一个主题:便利背后的陷阱,再次强调了软件开发的一种反模式:


开发团队一般为了图方便,而在其技术生态系统的复杂环节中,引入一些不合理的行为,从而欠下长期存在的技术债务,并会引发更糟的问题。这种例子不胜枚举,包括将数据库作为集成点,使用 Kafka 作为全局编排器,以及将业务逻辑代码混杂到基础设施代码中。诚如雷达中所说,这种反模式在软件开发中不胜枚举,开发团队必须时刻警惕,精心设计,持续地进行软件架构治理活动,避免为图一时之便而选择不合理的设计,欠下更多难以偿还的 技术债


为了更深刻理解这种反模式带来的问题,我们先来看一个典型案例:

从一个 BFF 优化案例谈起

这个案例选择了一个在BFF(Backends For Frontends)中实现稍复杂的接口,但并不是最复杂的接口。接口的逻辑参见下图:



可视化永远是发现问题最好的手段,上图中描述的接口复杂度一目了然,甚至有点触目惊心,一个 API 背后的逻辑居然能复杂到这个程度,如果不加梳理并可视化出来我们可能没有这么直观的感觉。这是在 BFF 暴露给前端的接口,实现过程中需要调用后端 10+个服务,进行几十次的服务间调用。在这几十次服务间调用过程中,有大量的读操作,以及近 10 次的跨服务写操作,读操作主要为了满足写操作的数据组装要求。



为了更清楚地理解这个接口设计背后的原因,我们再从业务逻辑的角度来看看这个接口都做了什么?这个接口有大量的写操作,可以从近 10 次的写操作中直观地看到一些端倪。通过上图中的时序,相信大家已经能看出一些问题了,咱们从业务和技术两个视角来一起看下这个接口:


  • 业务视角

把上面的关键功能快速分类,可以分成两块:一块是更新维修项状态,以及由此触发的维修单状态和维修商品状态更新。另一块是根据更新后的状态,生成相关文档,并记录文档和维修项的关系。

通常情况下,文档的打印都不是一次性的功能,会有多次打印的需求,但数据状态更新是一次性的,因此将这两大块功能放到一个逻辑背后是不合适的,使用频率不同,对失败的容忍程度也不同。

  • 技术视角

技术上的问题比较突出,重点总结为以下几点:

  • 问题一、BFF 承载了过多的业务。从上面的两大块业务功能来看,如果去掉这个 BFF,后端是不具备完整的业务能力的。这正是我在《BFF避坑指南》中描述的一个 BFF 实施常见问题,将 BFF 实现成了企业级服务总线(ESB)。后端服务只需要具备必要的增删改查接口,BFF 就可以完成前端的大部分需求。这样的 BFF 以一己之力承载了前端所有的业务,最终一定会走向大泥球,成为架构中的瓶颈和脆弱点。

  • 问题二、后端服务接口设计不是面向业务能力,而是面向数据。在这个事例中,一个 BFF 接口中要调用 3 个维修单服务接口才能完成完整的逻辑,维修单服务并没有将完整的业务能力内化在自己的服务内,而是提供了一些可以组合的接口,这也是开发者将大量逻辑写到 BFF 中的众多原因之一,或者说是 BFF 这种实践思想的一种后果。

  • 问题三、后端服务间数据关系比较紧密,耦合较重。一个业务状态的更新会涉及三个后端服务数据的更新,这背后的坏味道就是服务间耦合较重,边界不清晰,会导致大量业务功能需要多个服务配合才能完成。

  • 问题四、一个接口完成多次写操作,很难保证数据一致性。任何一个写接口的失败都会中断整个流程,而中断点不同,产生的数据一致性问题也不一样,在不采用分布式事务的情况下,这个接口上线后一旦产生问题,都将是非常棘手的。

  • 问题五、接口逻辑过于复杂,很难保证性能,稳定性差。几十次的跨服务间调用,即便每个调用都是毫秒级响应,这个接口的性能最好也只有几百毫秒,稍有波动就会上升到秒级,甚至更差,很难保证线上的稳定性,在有网络波动或异常的情况下,用户体验极差。

BFF 治理的原则与措施

上面的案例虽然不能覆盖 BFF 实践过程中的所有问题,但大部分典型的问题都暴露出来了。我们可以借着这个案例来讨论如何在实践中优化 BFF 的设计,达到治理的目的。


在给出改进方案之前,为了保证方向的正确性,我们先看下 BFF 的设计原则:

  • BFF 为前端而生,关注点在提升前端用户体验。

  • BFF 不承载业务能力,业务逻辑要下沉到合适的后端服务中。

  • BFF 不承载特定技术能力,必要时可以建立专门的服务承载,如文档打印、Excel 生成、算法逻辑等。

  • BFF 不做后端服务的集成层,某个后端服务的数据变更需要同步到其他服务,不能通过 BFF 实现。


仍然以上面案例里的场景为例,经过上面的分析,关键的问题已经找到了,就可以对症下药了。还是分两个视角来看:


  • 业务视角

从业务视角的优化显而易见,就是优化现有交互流程,将这一步操作改为两步,先完成业务数据的逻辑变更,再进行文档的逻辑处理。

  • 技术视角

从分析中可以看到,BFF 暴露出来的问题其实不仅仅是 BFF 自身的问题,也反映了后端服务的问题,因此要治理 BFF,首先要对后端的服务进行优化治理,再调整 BFF 内部的问题:

  • 从业务能力出发,重新审视后端服务之间的边界,必要时将耦合紧密的服务进行合并。

  • 重构后端服务提供的接口,面向业务提供接口。比如案例中更新维修单状态后,需要记录维修历史,需要关闭维修单,这些逻辑都在维修单服务中通过逻辑的关联处理完成。

  • 将 BFF 中的业务逻辑下沉到合适的后端服务中,后端服务之间要保持有效的通信机制,保证数据变更引发的连锁更新可以有序准确地完成,而不是由 BFF 作为集成媒介,在有写操作的场景下,BFF 只调用具备这个业务能力的后端服务接口,由这个后端服务负责处理所有相关数据的更新。在案例中,维修项和维修单的状态更新,应该根据前面的业务能力分析,放到某一个后端服务中来控制,或者放到二者合并后的服务中,最后再由这个后端服务负责完成与商品服务之间的数据更新。

  • 将 BFF 中的特定技术能力抽取成共享库,或者下沉建立服务。在案例中,生成文档的功能就可以建立一个单独的服务来处理,既解决 BFF 的问题,也能提供更好的复用能力。


在这些优化梳理和落地的过程中,一定还会发现其他相同或类似的问题,任何一个软件架构走到需要治理的地步都不是一个接口的问题,一定是一系列相互关联的问题,往往优化的过程中需要一起考虑,站在更高的视角来统一规划。

BFF 治理的方向总结

在微服务架构下,BFF 模式是非常必要的一种实践,特别是在微服务比较多的情况下,BFF 分离了前后端,可以让前端和后端更专注在各自的领域。在软件架构中,边界的处理是最难的,BFF 作为中间这一层,作用非同小可,其落地实践对架构的影响至关重要。BFF 治理是微服务架构下的软件架构治理中非常重要的一部分,通过 BFF 治理也能发现很多前端或后端设计的问题。


经过上面案例的分析,总结一下 BFF 治理的主要方向:

  • 首先分析 BFF 问题背后是不是存在后端服务设计问题,优先解决后端服务的设计问题。

  • 从业务上分析 BFF 接口的职责,保证接口职责单一。

  • 将 BFF 中业务能力下沉到后端服务。

  • 将 BFF 中需要复用的技术能力抽取成共享库或下沉建立后端服务。

  • 避免一个 BFF 接口依赖过多的后端服务,根据系统复杂度来看,最多依赖不超过 5 个后端服务为宜。

  • 避免一个 BFF 接口多次写操作,不滥用 BFF 站在上帝视角所拥有的权利,各司其职。


BFF (Backends For Frontends)是为前端设计的后端,不可图一时之方便而越俎代庖,将大部分该由后端服务提供的能力据为己有,而更应该关注在前端的体验优化上,做好前后端的隔离,让前后端能够各司其职,合理高效协作。

发布于: 刚刚阅读数: 2
用户头像

码猿外

关注

功不求戾,但求有恒 2018.10.07 加入

Thoughtworks首席咨询师,CAC认证专业敏捷教练,资深软件架构师 拥有10多年的架构设计和敏捷软件开发管理经验,专注于分布式软件架构设计、微服务架构设计和敏捷软件开发。 个人主页:https://maguangguang.xyz

评论

发布
暂无评论
BFF治理与优化实践_架构_码猿外_InfoQ写作平台