API 网关与 BFF 架构
网关是微服务架构的流量入口,BFF 是适配多端体验的专用层。两者结合实现灵活的前后端协作。
1. API 网关核心职责
Client
↓
┌───────────────┐
│ API Gateway │ ← 流量入口
└───────────────┘
│
┌───────────────┼───────────────┐
↓ ↓ ↓
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Order │ │ Payment │ │ User │
│ Service │ │ Service │ │ Service │
└──────────┘ └──────────┘ └──────────┘
功能矩阵
| 职责 | 说明 |
|---|---|
| 请求路由 | 按路径/Host/Header 转发到后端服务 |
| 负载均衡 | 多种 LB 算法:Round Robin、Least Conn |
| 认证授权 | JWT 校验、OAuth 集成、RBAC |
| 限流熔断 | 令牌桶限流、熔断状态机 |
| 协议转换 | HTTP ↔ gRPC、REST ↔ GraphQL |
| 日志监控 | 请求日志、延迟分布、错误率 |
| 灰度发布 | 按用户比例/Header 路由 |
2. 网关选型
| 网关 | 特点 | 适用场景 |
|---|---|---|
| Nginx/OpenResty | 高性能、Lua 扩展 | 简单路由、高并发入口 |
| Kong | 插件丰富、企业级 | 全功能 API 管理 |
| Apinto | 国产开源、轻量 | 国内生态替代 |
| Spring Cloud Gateway | Java 生态、Spring 集成 | Spring 体系微服务 |
| Envoy | 云原生、Service Mesh | K8s + Istio 场景 |
| Traefik | 自动服务发现 | 云原生动态路由 |
3. BFF 模式
Backend for Frontend:为不同客户端提供定制化的 API。
┌─────────┐
│ Web │────────────────→ Web BFF ──→ 聚合后端
├─────────┤
│ Mobile │────────────────→ Mobile BFF ──→ 聚合后端
├─────────┤
│ Admin │────────────────→ Admin BFF ──→ 聚合后端
└─────────┘
BFF vs 网关
| 对比 | 网关 | BFF |
|---|---|---|
| 职责 | 通用横切 | 业务聚合、数据适配 |
| 关注点 | 安全、限流、路由 | 响应结构、数据裁剪 |
| 复用性 | 全局统一 | 每个客户端独立 |
| 示例 | JWT 校验 | Web 端返回更多字段 |
BFF 实践要点
// Web BFF:聚合多服务,返回完整数据
async function getOrderDetail(orderId) {
const [order, payment, logis] = await Promise.all([
orderService.get(orderId),
paymentService.get(orderId),
logisticsService.get(orderId)
]);
return { order, payment, logistics: logis };
}
// Mobile BFF:精简响应,减少数据量
async function getOrderSummary(orderId) {
const order = await orderService.get(orderId);
return { id: order.id, status: order.status, total: order.total };
}
4. GraphQL 网关
为何选择 GraphQL
# 客户端决定要什么数据
query {
order(id: "123") {
id
status
items { name price }
user { name avatar }
}
}
优势:
- 精确获取,避免 Over-fetching
- 一次请求聚合多资源
- 强类型 Schema 作为 API 契约
Schema Stitching / Federation
// Apollo Federation:多个服务各自维护子 Schema
const gateway = new ApolloGateway({
serviceList: [
{ name: 'orders', url: '...' },
{ name: 'users', url: '...' }
]
});
// Gateway 自动合并为统一查询入口
GraphQL 网关的权衡
| 优势 | 挑战 |
|---|---|
| 请求效率高 | N+1 查询问题 |
| 类型安全 | 服务端复杂度 |
| 版本管理灵活 | 缓存策略复杂 |
| 文档即代码 | 学习成本 |
5. 认证与授权策略
典型认证流
Client → Auth Server → Token
│
│ (携带 Token)
↓
Gateway → 验签/鉴权 → 透传 UserID → Backend
网关层实现
# Kong 插件示例
plugins:
- name: jwt
config:
uri_param_names: [jwt]
claims_to_verify: [exp]
- name: rate-limiting
config:
minute: 60
微服务间调用
方案 A:网关统一鉴权,Service 间信任传递
└─ 简单但不适合内部安全要求高场景
方案 B:Service Mesh mTLS + 服务鉴权
└─ 端到端安全,但复杂度较高
6. 性能优化
| 策略 | 说明 |
|---|---|
| 连接池 | 复用后端连接,减少 TCP 握手 |
| 响应缓存 | Cache-Control 策略、Redis 缓存 |
| 异步聚合 | 并发请求下游服务 |
| 边缘缓存 | CDN 缓存静态 API |
| 请求合并 | 窗口期内合并相同请求 |
总结
| 组件 | 核心能力 | 代表工具 |
|---|---|---|
| API 网关 | 统一入口、安全、治理 | Kong, Envoy, Spring Gateway |
| BFF | 客户端适配、数据聚合 | Node.js, Java |
| GraphQL | 灵活查询、服务联邦 | Apollo, Hasura |
网关是门面,BFF 是翻译。二者配合,为微服务提供统一且灵活的对外接口。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。