BFF 是什么
BFF(Backend for Frontend)为每一类客户端提供专属的聚合层:按端的展示需求裁剪字段、并行聚合多个后端服务、处理端侧鉴权与缓存策略。它解决的是一个常见矛盾——用同一个通用接口适配所有客户端时,要么字段冗余(移动端浪费流量),要么为某一端特化而让其他端被迫接受额外复杂度。BFF 让每端可以按自己的节奏演进,代价是多了一层需要维护的服务。
基本信息
| 职责 | 聚合调用、字段裁剪、鉴权适配、端侧缓存策略 |
|---|---|
| 边界 | 不承载核心业务规则,逻辑可随端演进 |
| 部署 | 按前端团队归属维护,独立发布 |
| 数量 | 按客户端类型划分(Web、移动、第三方),不按页面划分 |
典型使用场景
- 移动端首屏优化:一次请求聚合多服务数据,减少往返与载荷
- 多端字段差异:Web 需要完整字段,移动端只要精简子集
- 鉴权适配:把不同端的令牌与会话方式转换成统一的后端调用凭证
- 灰度与实验:端侧实验逻辑放在 BFF,避免污染核心服务
- 降级兜底:某个下游不可用时返回默认值或缓存内容,保证页面可渲染
BFF 职责边界
| 放在 BFF | 不放在 BFF |
|---|---|
| 字段裁剪与格式适配 | 核心业务规则 |
| 多服务聚合与并行调用 | 跨端共享的领域逻辑 |
| 端侧鉴权与缓存策略 | 数据持久化与强事务 |
| 降级与默认值兜底 | 领域事件的生产 |
聚合调用示意(伪代码)
聚合调用示意(伪代码)
async function getHome(userId):
[profile, orders, coupons] = await parallel(
userSvc.get(userId),
orderSvc.recent(userId, limit = 3),
couponSvc.available(userId),
)
return {
name: profile.name, # 字段裁剪
orders: orders.map(toOrderCard), # 面向端的结构调整
couponCount: coupons.length,
}
# 单一子调用失败时返回降级值,页面整体仍可渲染使用要点
- BFF 数量与前端类型匹配即可:按页面拆分会带来重复代码与运维负担
- 聚合调用要设独立超时与部分失败策略,避免一个慢依赖拖垮整个页面
- 端侧缓存策略写在 BFF 或网关,不要让核心服务感知端的缓存需求
- 把“端专属逻辑”和“共享业务规则”分开:共享规则下沉到领域服务,避免多端各写一份
- 监控按端拆分:不同端的错误率与延迟要能独立观察,否则问题会被平均值掩盖
BFF 数量与前端类型匹配即可;按页面拆分 BFF 会带来重复代码与运维负担,聚合逻辑的复用价值通常低于维护成本。
BFF 依赖被多个下游聚合,任一依赖超时都可能影响整页:必须为每个子调用单独设置超时与降级值,否则聚合层会把局部故障放大成全端不可用。