1. BFF 架构概述
1.1 BFF 模式的定义
BFF(Backend For Frontend) 是一种面向特定前端客户端(Web、iOS、Android、小程序等)提供专属后端接口的架构模式。其核心思想是:每种前端客户端都拥有一个专属的后端服务,该服务负责聚合下游微服务的数据、裁剪响应字段、适配客户端协议,从而让前端不再直接面对复杂、通用、臃肿的微服务网关。
关键认知: BFF 不是简单的“中间层”,而是一种按端隔离的接口适配层。每个 BFF 只服务一种前端,拥有独立的接口契约、数据模型和业务编排逻辑。
BFF 模式最早由 SoundCloud 在 2015 年提出,用于解决“一个后端 API 服务多个前端”时出现的接口膨胀、字段冗余、协议不匹配等问题。其核心特征包括:
- 按端隔离: 每个前端(Web / iOS / Android / 小程序)拥有独立的 BFF 服务。
- 接口定制: BFF 为特定前端“量身定制” API,只返回该端需要的字段和数据格式。
- 聚合编排: BFF 负责调用多个下游微服务,将结果聚合、转换后返回给前端。
- 协议适配: BFF 可以将后端 gRPC / Thrift / AMQP 协议转换为前端友好的 HTTP / JSON / GraphQL。
- 轻量无状态: BFF 通常不包含核心业务逻辑,只做编排、转换和路由,保持无状态以便水平扩展。
1.2 BFF 在微服务架构中的位置
在典型的微服务架构中,BFF 位于前端客户端与下游微服务之间,属于接入层的一部分。下图展示了 BFF 在整体架构中的位置:
从架构分层来看,BFF 处于接入层与业务层之间,承担以下职责:
| 架构层 | 组件 | 职责 |
|---|---|---|
| 客户端层 | Web / iOS / Android / 小程序 | UI 渲染、用户交互、本地缓存 |
| 接入层 | API Gateway / 负载均衡 / CDN | 统一入口、限流、鉴权、日志、路由 |
| BFF 层 | Web BFF / iOS BFF / Android BFF | 接口定制、数据聚合、协议适配、字段裁剪 |
| 业务层 | 用户服务 / 订单服务 / 商品服务 | 核心业务逻辑、数据持久化、领域事件 |
| 基础设施层 | 数据库 / 消息队列 / 缓存 / 注册中心 | 数据存储、异步通信、服务发现 |
1.3 BFF 与 API Gateway 的区别
BFF 和 API Gateway 是微服务架构中两个容易混淆的概念。虽然它们都位于客户端与后端之间,但职责边界、粒度、定制化程度存在本质差异。下表从多个维度进行对比:
| 对比维度 | API Gateway | BFF |
|---|---|---|
| 核心职责 | 统一入口、路由转发、限流熔断、安全认证 | 接口定制、数据聚合、协议适配、字段裁剪 |
| 粒度 | 粗粒度,面向所有客户端提供通用 API | 细粒度,面向特定前端提供专属 API |
| 定制化 | 低,通常不针对单个前端做字段裁剪 | 高,每个 BFF 按前端需求定制接口 |
| 数量 | 通常 1 个(或主备) | 多个,每个前端客户端对应一个 BFF |
| 业务逻辑 | 不包含业务逻辑,只做通用处理 | 包含轻量编排逻辑,但不包含核心领域逻辑 |
| 协议转换 | 通常只做 HTTP 协议转发 | 可做 gRPC → HTTP / Thrift → JSON 等转换 |
| 典型实现 | Kong / Zuul / Spring Cloud Gateway / Nginx | Go 编写的轻量 HTTP 服务 / Node.js Express / GraphQL |
| 部署方式 | 独立部署,作为基础设施组件 | 按端独立部署,与前端版本对齐 |
实践建议: 在 Go 微服务架构中,通常API Gateway + BFF 组合使用。API Gateway 负责全局横切关注点(鉴权、限流、日志),BFF 负责按端定制接口。两者不是二选一,而是互补关系。
下图展示了 API Gateway 与 BFF 在架构中的协作关系:
常见误区: 不要试图用 API Gateway 替代 BFF。Gateway 的职责是“通用入口管控”,BFF 的职责是“按端定制接口”。将字段裁剪、数据聚合逻辑塞进 Gateway 会导致 Gateway 变得臃肿、难以维护,且无法按端独立迭代。
1.4 何时选择 BFF
在 Go 微服务架构中,以下场景强烈建议引入 BFF 模式:
- 多端共存: 同时支持 Web、iOS、Android、小程序,各端接口需求差异明显。
- 接口膨胀: 后端微服务 API 字段过多,前端只需要其中 20% 的字段,且各端需要的字段不同。
- 协议不统一: 后端使用 gRPC / Thrift,前端需要 HTTP / JSON 接口。
- 编排复杂: 单个页面需要调用 3 个以上微服务,且聚合逻辑因端而异。
- 独立迭代: 前端版本迭代速度快,需要后端接口按端独立演进,避免互相影响。
Go 语言优势: Go 的轻量协程(goroutine)和高效 HTTP 库(net/http、gin、echo)非常适合构建 BFF 层。BFF 通常需要并发调用多个下游微服务,Go 的并发模型可以轻松实现“扇出(fan-out)”聚合,且资源开销极低。