微服务拆分精讲 / 第 06 章:API 网关
第 06 章:API 网关
API 网关是微服务的"门面"——对外统一入口,对内路由分发,兼守卫和调度于一身。
6.1 为什么需要 API 网关
6.1.1 没有网关的困境
客户端直接访问微服务(无网关)
┌────────┐ ┌──────────┐
│ Web │───────────────────────▶│ 用户服务 │
│ App │───────────────────────▶│ 订单服务 │
└────────┘───────────────────────▶│ 商品服务 │
│ 支付服务 │
┌────────┐ │ 通知服务 │
│ Mobile │───────────────────────▶│ 搜索服务 │
│ App │───────────────────────▶│ ... │
└────────┘ └──────────┘
问题:
1. 客户端需要知道所有服务地址
2. 每个服务都要实现认证/限流/日志
3. 跨域问题分散在各个服务
4. 协议转换无法统一处理
5. 客户端与服务强耦合
6.1.2 引入网关后
┌────────┐ ┌──────────────────┐ ┌──────────┐
│ Web │ │ API Gateway │ │ 用户服务 │
│ App │────▶│ │────▶│ 订单服务 │
└────────┘ │ • 路由分发 │────▶│ 商品服务 │
│ • 认证授权 │────▶│ 支付服务 │
┌────────┐ │ • 限流熔断 │────▶│ 通知服务 │
│ Mobile │────▶│ • 日志监控 │────▶│ 搜索服务 │
│ App │ │ • 协议转换 │ │ ... │
└────────┘ │ • 负载均衡 │ └──────────┘
└──────────────────┘
优势:
1. 客户端只需知道网关地址
2. 横切关注点在网关统一处理
3. 服务可以独立演进
6.2 网关核心功能
6.2.1 功能矩阵
| 功能 | 说明 | 重要程度 |
|---|---|---|
| 请求路由 | 根据路径/域名/Header 路由到不同服务 | ⭐⭐⭐⭐⭐ |
| 负载均衡 | 将请求分发到服务的多个实例 | ⭐⭐⭐⭐⭐ |
| 认证授权 | 验证 JWT/OAuth2 Token | ⭐⭐⭐⭐⭐ |
| 限流熔断 | 防止服务过载、级联故障 | ⭐⭐⭐⭐ |
| 请求/响应转换 | 修改 Header、Body、协议转换 | ⭐⭐⭐⭐ |
| 日志与监控 | 记录请求日志、采集指标 | ⭐⭐⭐⭐ |
| SSL 终止 | 在网关层处理 HTTPS | ⭐⭐⭐ |
| 缓存 | 缓存频繁请求的响应 | ⭐⭐⭐ |
| API 版本管理 | v1/v2 路由切换 | ⭐⭐⭐ |
| 灰度发布 | 按比例/条件路由到不同版本 | ⭐⭐⭐ |
6.2.2 路由配置示例
路由规则示例:
┌──────────────────────────────────────────────────────────┐
│ API Gateway 路由表 │
├──────────────────────────────────────────────────────────┤
│ │
│ 前缀路由: │
│ /api/v1/users/** ──▶ user-service:8080 │
│ /api/v1/orders/** ──▶ order-service:8080 │
│ /api/v1/products/** ──▶ product-service:8080 │
│ /api/v1/payments/** ──▶ payment-service:8080 │
│ │
│ Header 路由: │
│ X-Tenant: premium ──▶ premium-user-service:8080 │
│ │
│ 权重路由(灰度): │
│ /api/v2/orders/** ──▶ order-service-v2:8080 (20%) │
│ ──▶ order-service-v1:8080 (80%) │
└──────────────────────────────────────────────────────────┘
6.2.3 限流策略
| 策略 | 粒度 | 说明 | 适用场景 |
|---|---|---|---|
| 全局限流 | 服务级 | 限制服务总 QPS | 防止服务过载 |
| 用户限流 | 用户级 | 每个用户 N 次/秒 | 防止单用户滥用 |
| IP 限流 | IP 级 | 每个 IP N 次/分钟 | 防止爬虫/攻击 |
| 接口限流 | API 级 | 特定接口单独限流 | 保护高成本接口 |
| 滑动窗口 | 时间窗口 | 平滑限制 | 精确控制 |
限流算法对比:
┌────────────────┬──────────┬──────────┬──────────┐
│ 算法 │ 平滑度 │ 内存占用 │ 实现难度 │
├────────────────┼──────────┼──────────┼──────────┤
│ 固定窗口 │ 低 │ 低 │ 低 │
│ 滑动窗口 │ 中 │ 中 │ 中 │
│ 漏桶 (Leaky) │ 高 │ 低 │ 中 │
│ 令牌桶 (Token) │ 高 │ 低 │ 中 │
└────────────────┴──────────┴──────────┴──────────┘
6.3 认证与授权
6.3.1 网关层认证流程
┌────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ 客户端 │ │ API 网关 │ │ 认证服务 │ │ 业务服务 │
└───┬────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │ │
│ 1.请求 + JWT │ │ │
│─────────────▶│ │ │
│ │ │ │
│ │ 2.验证 JWT │ │
│ │ (本地验证/ │ │
│ │ 远程校验) │ │
│ │─────────────▶│ │
│ │ │ │
│ │ 3.验证通过 │ │
│ │◀─────────────│ │
│ │ │ │
│ │ 4.转发请求 │ │
│ │ (附加用户信息)│ │
│ │─────────────────────────▶ │
│ │ │ │
│ │ │ 5.响应 │
│ │◀──────────────────────────│
│ │ │ │
│ 6.响应 │ │ │
│◀─────────────│ │ │
6.3.2 JWT 验证配置示例(Kong)
# Kong JWT 插件配置
plugins:
- name: jwt
config:
# JWT 密钥来源
key_claim_name: kid
claims_to_verify:
- exp # 验证过期时间
- iss # 验证签发者
# 将解码后的 claims 转发给上游服务
run_on_preflight: false
6.4 API 网关选型
6.4.1 主流网关对比
| 特性 | Kong | Envoy | APISIX | Spring Cloud Gateway | Nginx |
|---|---|---|---|---|---|
| 语言 | Lua/Go | C++ | Lua | Java | C |
| 配置 | Admin API/声明式 | xDS API | Admin API/YAML | Java/配置文件 | 配置文件 |
| 性能 | 极高 | 极高 | 极高 | 高 | 极高 |
| 扩展性 | 插件丰富 | Filter/ WASM | 插件丰富 | 过滤器链 | 模块/脚本 |
| 服务发现 | DNS/Consul | xDS/EDS | DNS/Etcd/K8s | Eureka/Nacos | 需配置 |
| 管理界面 | ✅ Kong Manager | ❌ 需第三方 | ✅ Dashboard | ❌ | ❌ |
| 适用场景 | 通用 | Service Mesh | 通用 | Spring 生态 | 静态代理 |
6.4.2 Kong 网关
Kong 是目前最流行的开源 API 网关之一,基于 OpenResty(Nginx + Lua),拥有丰富的插件生态。
Kong 架构:
┌──────────────────────────────────────────────────────┐
│ Kong Gateway │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 认证 │ │ 限流 │ │ 日志 │ 插件链 │
│ │ (JWT/ │ │ (Rate │ │ (Log/ │ │
│ │ OAuth) │ │ Limit) │ │ Trace) │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │ │ │ │
│ ┌────┴────────────┴────────────┴────┐ │
│ │ 请求处理管道 │ │
│ │ Access → Header Filter → Body │ │
│ │ Filter → Log → Response │ │
│ └────────────────┬──────────────────┘ │
│ │ │
│ ┌────────────────┴──────────────────┐ │
│ │ Upstream (上游) │ │
│ │ Load Balancing → Health Check │ │
│ └───────────────────────────────────┘ │
└──────────────────────────────────────────────────────┘
Kong 常用命令:
# 添加服务
curl -X POST http://localhost:8001/services \
--data name=user-service \
--data url=http://user-service:8080
# 添加路由
curl -X POST http://localhost:8001/services/user-service/routes \
--data name=user-routes \
--data 'paths[]=/api/v1/users'
# 启用限流插件
curl -X POST http://localhost:8001/services/user-service/plugins \
--data name=rate-limiting \
--data config.second=100 \
--data config.policy=redis \
--data config.redis_host=redis
6.4.3 Envoy Proxy
Envoy 是 Lyft 开发的高性能代理,是 Service Mesh(Istio)的数据面。
Envoy 架构:
┌──────────────────────────────────────────────────────┐
│ Envoy Proxy │
│ │
│ ┌───────────────────────────────────────────────┐ │
│ │ Listener (监听器) │ │
│ │ ┌───────────┐ ┌───────────┐ │ │
│ │ │ HTTP │ │ TCP │ │ │
│ │ │ Filter │ │ Filter │ │ │
│ │ │ Chain │ │ Chain │ │ │
│ │ └───────────┘ └───────────┘ │ │
│ └──────────────────┬────────────────────────────┘ │
│ ▼ │
│ ┌───────────────────────────────────────────────┐ │
│ │ Cluster (集群) │ │
│ │ Service Discovery → Load Balancing → Health │ │
│ └───────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────┐ │
│ │ Admin API │ │
│ │ /config_dump /stats /clusters /listeners │ │
│ └───────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────┘
Envoy 配置示例:
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 8080
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
route_config:
virtual_hosts:
- name: backend
domains: ["*"]
routes:
- match:
prefix: "/api/v1/users"
route:
cluster: user_service
- match:
prefix: "/api/v1/orders"
route:
cluster: order_service
http_filters:
- name: envoy.filters.http.router
clusters:
- name: user_service
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: user_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: user-service
port_value: 8080
6.5 BFF 模式(Backend for Frontend)
6.5.1 概念
BFF 为每种客户端(Web、Mobile、小程序)提供定制的后端网关。
传统单网关:
┌────────┐ ┌─────────┐ ┌──────────┐
│ Web │────▶│ │────▶│ 用户服务 │
│ Mobile │────▶│ API GW │────▶│ 订单服务 │
│ 小程序 │────▶│ │────▶│ 商品服务 │
└────────┘ └─────────┘ └──────────┘
(同一套API,客户端各自处理差异)
BFF 模式:
┌────────┐ ┌─────────┐
│ Web │────▶│ Web BFF │────┐
└────────┘ └─────────┘ │ ┌──────────┐
├───▶│ 用户服务 │
┌────────┐ ┌─────────┐ ├───▶│ 订单服务 │
│ Mobile │────▶│App BFF │────┤ │ 商品服务 │
└────────┘ └─────────┘ │ └──────────┘
│
┌────────┐ ┌─────────┐ │
│ 小程序 │────▶│ Mini BFF│────┘
└────────┘ └─────────┘
(每个BFF为对应客户端定制API)
6.5.2 BFF vs API Gateway
| 维度 | API Gateway | BFF |
|---|---|---|
| 职责 | 通用横切功能 | 客户端定制化 |
| 粒度 | 一个网关服务所有客户端 | 每个客户端一个 BFF |
| 逻辑 | 路由、认证、限流 | 数据聚合、格式转换 |
| 团队 | 平台团队维护 | 业务前端团队维护 |
6.6 业务场景:电商 API 网关设计
┌──────────────────────────────────────────────────────────┐
│ 电商 API 网关完整配置 │
├──────────────────────────────────────────────────────────┤
│ │
│ 路由规则: │
│ /api/v1/users/** → user-service (10 实例) │
│ /api/v1/products/** → product-service (20 实例) │
│ /api/v1/orders/** → order-service (15 实例) │
│ /api/v1/payments/** → payment-service (8 实例) │
│ /api/v1/search/** → search-service (5 实例) │
│ │
│ 限流配置: │
│ 全局: 10000 QPS │
│ /api/v1/orders/**: 2000 QPS (下单接口单独限流) │
│ /api/v1/payments/**: 500 QPS (支付接口严格限流) │
│ 每用户: 100 QPS │
│ │
│ 认证配置: │
│ /api/v1/users/login → 不需要认证 │
│ /api/v1/users/register → 不需要认证 │
│ /api/v1/** → JWT 认证 │
│ /api/v1/admin/** → JWT + Admin 角色 │
│ │
│ 缓存配置: │
│ /api/v1/products/{id} → 缓存 60 秒 │
│ /api/v1/categories → 缓存 300 秒 │
└──────────────────────────────────────────────────────────┘
⚠️ 注意事项
- 网关不是业务逻辑的地方——复杂的业务逻辑应该在服务内部处理
- 避免单点故障——网关必须高可用部署(至少 2 个实例)
- 监控网关延迟——网关本身不应成为性能瓶颈
- 版本兼容——API 版本管理策略要提前规划
- 安全加固——网关是攻击面最大的入口,需要额外安全措施
📖 扩展阅读
- Kong Documentation (docs.konghq.com) — Kong 网关完整文档
- Envoy Proxy Documentation (envoyproxy.io) — Envoy 官方文档
- Chris Richardson - API Gateway Pattern — API 网关模式详解
- Netflix Zuul — 早期 Java 网关的代表(已被 Spring Cloud Gateway 替代)
- APISIX (apisix.apache.org) — Apache 顶级项目,国产高性能网关
本章小结
| 要点 | 说明 |
|---|---|
| 核心功能 | 路由、认证、限流、监控、协议转换 |
| 主流选型 | Kong(通用)、Envoy(Service Mesh)、APISIX(国产) |
| BFF 模式 | 为不同客户端提供定制化后端 |
| 关键原则 | 不放业务逻辑、高可用部署、安全加固 |
📌 下一章:第 07 章:服务通信 — 同步 REST/gRPC 和异步消息的通信模式选型。