微服务 BFF 架构设计

news/2024/12/13 2:27:56/

在现代软件开发中,由于程序、团队、数据规模太大,需要把企业的业务能力进行复用,将领域服务剥离,提供通用能力,避免重复建设和代码;另外服务功能的弹性能力不一样,比如定时任务、数据同步明确的技术诉求,甚至一些“政治”因素,微服务架构成为了势不可挡的趋势席卷而来。随着微服务架构和前后端分离思想的流行,BFF 也是微服务架构必须考虑的一个设计组件。

一、Why BFF:承前启后 

BFF即 Backends For Frontends (服务于前端的后端),由于微服务众多,需要一个统一入口根据不同的业务场景作为前端集成使用。

面向后端:BFF 隔离了因不同渠道前端 UI 展示对后端 API 的需求,企业可以在后端构建核心业务领域能力

面向前端:BFF 可以根据已有的后端 API,快速满足不同渠道的前端在 UI 展示上的需求,来不断提升用户体验

同时,BFF 可以帮助企业进行微服务架构的迁移或者演进。如下图所示,如果我们需要将一个大单体的架构迁移或演进成一个微服务的架构,可以先在前端和单体应用间加一个 BFF 层,通过 BFF 把单体的服务能力暴露给前端;然后我们可以把大单体拆分成领域服务或者中台,通过 BFF 或者前台(相对于中台的概念)把中台和领域服务组合和编排成前端需要的 API,这样中台和领域服务的变动也不会影响前端的用户体验。由此可见,后台架构的演进可以通过 BFF 来进行隔离;微服务架构内部的演进,微服务的拆分,也可以借助 BFF 来减少对前端的影响。

另外,由于进程间存在不同的资源类型,业务上存在不同的变化频度,我们会对进程间进行分层来获得最优的拓展方法。通常越靠近用户的层,它的需求和变化频度就越大,所以我们图中前后端的进程间架构采用了漏斗的形式。如果你的系统架构设计是反漏斗的,那么就需要反思架构设计是否合理。

二、典型的进程间微服务架构

我们以外卖系统为例,它的用户有订餐用户、餐饮商家、后台管理人员。它的渠道有手机 APP、微信小程序和 WEB 页面。在刚开始的时候,为了加快上线抢占市场,我们把它构建成了大单体但是前后端分离的形式。下图是初始的进程间架构。

随着业务的发展,接入的商家越来越多,订餐用户的个性化需求也复杂了起来,后台管理和一些报表功能也复杂起来了,研发团队的规模也从十几人变成了几百人了。因此高层决定把传统的单体架构转变为微服务架构,提高需求的上线效率。他们决定引入 BFF 来做架构的演进,但是有两种微服务架构,让决策团队出现了为难情绪。

薄 BFF

薄 BFF 的意思就是 BFF 的职责较少,也叫网关,主要负责将前端的路由转发后端的领域服务。当然一些通用的功能如鉴权、限流、熔断、服务降级、灰度路由等也可以放到其中。

厚 BFF

相对于薄 BFF,厚 BFF 算是真正意义上的 BFF,除了具有薄 BFF 的所有职能外,它可以接入不同的协议如 MQ 服务,WebSocket等;类似 DDD 领域驱动设计中的应用层,可以组合和编排不同的领域服务,避免了服务间的相互依赖。

 

微服务模式对比

下面的表格是薄厚两种 BFF 的对比。

模式

渠道独立多样性

聚焦领域服务

前端数据组装难易性

端到端交付

重复代码

薄BFF

厚BFF

对于薄 BFF,适合接入差异较小的应用,如企业内部使用的应用系统。用户群非常固定、交互方式统一、数据权限能找到规律,避免了重复代码。

对于厚 BFF,对不同的来源请求都使用了各自的入口服务承接,此结构成本较大,但对于接入渠道多样或业务场景复杂的系统来说较适合。另外Open API(可以看做是一种 BFF) 作为系统防腐层,有必要设计为有编排能力的 BFF。

三、BFF 的问题

前面说了引入 BFF 给我们微服务架构带来了诸多好处。但是引进了一个组件势必会带来不少问题。

1.  由于多个前端渠道会有不同的 BFF,往往会导致同样一个功能需要在不同 BFF 中来实现,会有大量的重复代码。

2.  BFF承载了过多的业务。当新的业务需求产生时,具体要在哪个后端领域服务中实现有时候不是一个很容易回答的问题,特别是不同的服务有不同的团队归属时,如果每个服务的归属团队都认为新的业务需求不是自己服务的业务范畴,特别是如果是前端或者BFF团队来牵头需求时,最可能的结果就是让 BFF 负责帮忙组合各个服务的功能,完成这个新的业务需求。渐渐地,BFF 朝着 ESB 的方向发展,变成了集成各个微服务,对外提供新能力的中间件。

3.  一个接口完成多次写操作,很难保证数据一致性。如果一个业务场景需要调用多个后端领域服务来更新或插入数据,那么数据的同步就是个问题。

4.  性能。既然有了 BFF,前端的设计是否可以放飞自我了,可以把想展示的信息一股脑都放在一起展示,极端情况下 BFF 可以获取到任意服务的数据进行组合,那么一个 BFF 接口需要调用了N个后端服务来拼凑前端需要的数据,那么这个接口的性能一定不会好。

四、BFF 的治理方向

针对这些问题,我们需要明确该如何治理 BFF。要治理就要有原则:

1.  BFF 为前端和业务场景而生,关注点在提升前端用户体验和对后端业务能力的编排上

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

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

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

有了原则,就有方向。BFF 的治理方向如下:

1.  优先解决后端服务的设计问题

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

3.  将BFF中业务能力下沉到后端领域服务

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

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

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


http://www.ppmy.cn/news/1152421.html

相关文章

一次c++监听Linux文件目录的实践

目的:监听系统/data/system/dropbox目录,解析出crash和ANR,并上传云端。 这里只记录如何监听这个目录和实践中遇到的问题。 使用的到技术: 1.inotify 2.epoll 3.thread 环境:android系统 demo测试: …

C语言【关键字】

C语言中32个关键词的含义和用途 分 类 关键字 含义和用途 基本数据类型 简单数据类型 int 声明整型变量或函数 char 声明字符型变量或函数 float 声明浮点型变量或函数 double 声明双精度变量或函数 特殊类型 register 声明寄存器变量 void 声明函数无返回…

软件测试/测试开发/人工智能丨聊聊AutoGPT那些事儿

点此获取更多相关资料 简介 在 ChatGPT 问世之后,大家很容易就发现其依然具备一些很难解决的问题,比如: Token 超出限制怎么办?(目前最新的 GPT4 支持最多8,192 tokens)。如何完全自动化?任务…

zookeeper应用场景(一)

一、zookeeper客户端api 1、官方Java客户端api 引入zookeeper client依赖 <dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.9.0</version> </dependency> 1&#xff09…

频繁GC问题原因总结

频繁GC 频繁的垃圾回收&#xff08;GC&#xff09;通常是由以下一些原因引起的&#xff1a; 内存分配过多&#xff1a;如果应用程序频繁地分配新的对象而不释放旧的对象&#xff0c;堆内存将快速用满&#xff0c;触发频繁的垃圾回收。这可能是由于代码中存在内存泄漏或不合理…

sql 注入(4), 盲注

sql 注入, 盲注 盲注适合在页面没有任何回显时使用. 测试页面有变化, 但是没有显示任何异常错误等信息. 情景: url: http://192.168.112.200/security/read.php?id1 服务器数据库名: learn一, boolean盲注 # 盲注可能需要一个一个字符去试探, 字符串处理函数经常会用到. 比…

软件测试/测试开发丨Python闭包与装饰器 学习笔记

点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接&#xff1a;https://ceshiren.com/t/topic/27720 闭包与装饰器 1、函数引用 Python 中定义的函数&#xff0c;也可以像变量一样&#xff0c;将一个函数名&#xff0c;赋值给另一个变量名&#xff…

【算法与数据结构】--常见数据结构--栈和队列

一、栈 栈&#xff08;Stack&#xff09; 是一种基本的数据结构&#xff0c;具有后进先出&#xff08;LIFO&#xff09;的特性&#xff0c;类似于现实生活中的一叠盘子。栈用于存储一组元素&#xff0c;但只允许在栈顶进行插入&#xff08;入栈&#xff09;和删除&#xff08;…