数据结构论坛

首页 » 分类 » 常识 » DDD系列文章第10篇BFF架构
TUhjnbcbe - 2023/7/6 19:25:00

全文约字,预计阅读时间11分钟。

导读

不管是通过DDD方法论设计新服务还是梳理老服务,绕不开的一点就是接口设计。接口设计时很容易犯的一个错就是经常会根据接口调用方的个性化场景(比如多种界面展示)设计出很多类似且重复性的接口,且接口的实现逻辑割裂、复用性差。为了让业务服务更加聚焦领域能力,根据领域能力设计对外接口,同时又要满足多样化的接口消费场景如前端展示,架构里往往需要引入BFF这一层。

01

BFF要解决什么问题

1.1问题

在用户体验至关重要的今天,程序展示界面丰富多样。比如同一个界面可能同时存在极简版、专业版,一个界面要展示多种数据,要连接的设备也层出不穷如小程序、APP、网页、客户端等等。归纳起来有这几类:

字段裁减App端往往只能展示少量信息,浏览器网页则需要全部信息,因此需要适配各端而裁减字段聚合和编排多种数据一个页面要展示多个服务端的数据,因此需要聚合多个API的数据(串行或并行编排多个API)接入平台工作通过组合多个已有系统的接口对外提供更具业务语义的能力,提供统一接入层服务数据格式转换面对服务端不同的数据格式,甚至有历史遗留系统,需要适配成前端展示更友好的格式前端的业务效果试验试验不同的展示方案效果,需要快速支持新业务方案上线

1.2分析

这些需求如果都在前端完成,则前端需要多次网络请求服务端数据,并且接口相关的适配逻辑不适合用前端技术来处理,效率不会高。但是如果一股脑丢到服务端来处理,则服务端模块的接口频繁修改带来稳定性下降。模块界限会变模糊,接口数量膨胀厉害。展示逻辑和领域逻辑混杂在一起,久而久之业务逻辑将变得难以维护。

从DDD角度看,提倡围绕领域业务能力进行接口设计,服务端应该聚焦领域自身能提供什么样的能力来设计接口,而展示相关的处理逻辑不应该是领域业务。因此可以得出这里的主要矛盾是前端的本质是提供良好的用户体验,必然会高频迭代,而服务端的业务逻辑和关键业务数据字段有行业特性,相对比较稳定,不会随着体验变化很大。那应该怎么办呢?

既然错不在前端也不在服务端,那么一般架构的做法是引入新的一层。业界的叫法是BFF(BackendForFrontend),即后端为前端编程。BFF源于SamNewman在微服务模式里提出。BFF其实也是微服务架构下的产物,通过引入BFF解耦了前后端,也对组织架构做了归属和指导。下图来自他的BFF文章:

02

BFF定位和技术选型

增加一层永远是解耦的大招,但BFF只是逻辑分层的名称,不是具体的技术。实现BFF的技术框架有多种。从BFF层的组织架构归属看,由前端团队或后端团队负责则会引入各自不同的技术选型。前端有NodeJS、GraphQL框架等,后端有Java、GraphQL框架、网关框架等。因此很多大厂的产品都有BFF层,但具体的实现各有不同。不妨来看一下BFF技术要考虑的4个方面的关键诉求。

2.1BFF的组织定位

康威定律是架构首要考虑到的,前端模式或者后端模式会决定BFF由不同技术栈的团队来承接,也直接影响着BFF层的技术架构演进方向。相应地这两种模式各有优缺点。但不管是前端团队来承接BFF还是后端团队,没有对错,应该根据组织自身的现状和发展来思考。

前端模式优点:前端团队负责,自主取数,减少跨团队沟通缺点:需要深入业务逻辑、需要掌握基础设施建设的能力后端模式优点:复用后端现有基础设施缺点:前端服务、bff服务和业务服务三者的职责和边界把控

2.2接口开发与编排

BFF层的接口编排技术包含几层含义:

传统接口方式连接供给和消费

即消费方每次都必须按照接口供给方规定的请求参数发起请求,获得请求出参数据。

供给方如何高效开发一个接口。正常的接口开发需要考虑接口端点暴露、请求参数和返回参数格式、请求路由和状态等。不管是NodeJS、Java、Go等语言都有现成的Web框架集成供给方如何高效支持串并行调用下游接口。BFF层的一个接口往往需要调用下游多个微服务接口,有串行调用也有并行调用。这点在各种编程语言也有比较好的支持,比如NodeJS的Promise等异步控制对象,Java里的CompleteFuture异步调用、Go里的协程等

从上面两点来看其实编程语言不是关键。如果业务和团队规模不是很大,建设BFF层到这里就够用了。但一旦业务和团队规模变大,展示和取数逻辑涉及的团队人员和接口数量激增,如何高效地完成重复性的接口开发和取数调用将变得关键。突破口往往都是某种意义上的元数据驱动。做到声明式的接口开发体验效果。

因此BFF层的建设将分化出底层框架开发和业务开发两类工作。业务开发以类似DSL(领域专属语言)的方式(比如XML/Json表达、甚至界面拖拽形式)定义出需要从哪些接口取哪些数据字段,做哪些数据加工动作。底层框架负责以标准化的步骤实现接口的定义、组装和调用。

消费方按需查询

即消费方可以在调用接口时表达自己想使用哪部分数据,从供给方获得按需的出参数据。通俗地讲就是消费方调用同一个接口时可以控制接口的出参数据。

业界的实现方案是Facebook开源的GraphQL接口查询标准,不同语言下有不同的实现框架。其中NodeJS下的Apollo框架使用较广,Java也有社区的开源实现。元数据驱动,如第一点所述。

按需查询的能力听上去很好,但实现的成本也高。因此需要深入理解产品和业务的形态,先回答到底有没有这种需求,值不值得去支持。

2.3BFF与API网关的关系

这个问题关系到BFF服务在整体架构里的定位。在没有BFF之前,微服务架构里一般都有一个反向代理层,即负责路由和转发来自外网的

1
查看完整版本: DDD系列文章第10篇BFF架构