首页/开发/系统分析与架构设计速查/BFF(Backend for Frontend)

BFF(Backend for Frontend)

为每类前端(Web、移动端、第三方)提供专属聚合层:按端裁剪字段、聚合多服务调用并处理差异化缓存;避免用一个通用接口适配所有客户端。

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 依赖被多个下游聚合,任一依赖超时都可能影响整页:必须为每个子调用单独设置超时与降级值,否则聚合层会把局部故障放大成全端不可用。

易错点

  • BFF 里堆核心业务规则,其他端无法复用,规则修改要改多份
  • 每个页面一个 BFF,重复代码与发布成本高,团队很快失去维护意愿
  • 聚合调用无独立超时与降级,单个依赖变慢导致整页不可用
  • 字段裁剪与核心服务的权限校验脱节,出现越权返回或字段泄露
  • 缺少按端的监控维度,某一端的异常被整体平均值掩盖

数据来源与参考

  • Sam Newman:Backends For Frontends(Pattern)
  • microservices.io:API Composition
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌