这是《Spring Boot 与 Spring Cloud 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 网关是外部流量进入内部系统的统一边界,负责路由、认证、限流、熔断、协议转换、观测和安全策略。它应该保持轻量稳定,避免承载业务逻辑。
19.1 网关职责
Client
-> Gateway
-> 路由
-> 认证
-> 限流
-> 日志
-> 负载均衡
-> Order Service
| 职责 | 说明 |
|---|---|
| 路由 | 按路径、Host、Header 转发 |
| 认证 | 验证 Token、签名 |
| 授权 | 判断可访问资源 |
| 限流 | 保护后端 |
| 熔断 | 阻止故障扩散 |
| 观测 | 记录访问日志和指标 |
| 安全 | TLS、WAF、CORS |
| 发布 | 灰度、蓝绿、金丝雀 |
不建议在网关写业务规则,例如复杂促销计算。网关逻辑越重,变更和故障影响越大。
19.2 Spring Cloud Gateway
依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway-server-webflux</artifactId>
</dependency>
配置:
server:
port: 8080
spring:
cloud:
gateway:
server:
webflux:
routes:
- id: order-route
uri: lb://order-service
predicates:
- Path=/api/orders/**
filters:
- name: Retry
args:
retries: 2
statuses: BAD_GATEWAY
- StripPrefix=0
Spring Cloud Gateway 基于 Reactive 技术栈,不适合直接使用阻塞 API。版本较新时配置命名可能有调整,以当前文档为准。
19.3 路由谓词
常用谓词:
| 谓词 | 说明 |
|---|---|
| Path | 路径匹配 |
| Method | HTTP 方法 |
| Header | 请求头 |
| Query | 查询参数 |
| Host | 域名 |
| Weight | 按权重路由 |
| Cookie | Cookie 匹配 |
示例:
routes:
- id: canary
uri: lb://order-service-v2
predicates:
- Path=/api/orders/**
- Header=X-Canary, true
路由顺序要明确,避免宽泛规则先匹配。
19.4 过滤器
全局过滤器:
@Component
public class TraceIdFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String traceId = Optional.ofNullable(exchange.getRequest().getHeaders().getFirst("X-Trace-Id"))
.orElseGet(() -> UUID.randomUUID().toString());
exchange = exchange.mutate()
.request(builder -> builder.header("X-Trace-Id", traceId))
.build();
exchange.getResponse().getHeaders().set("X-Trace-Id", traceId);
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -100;
}
}
过滤器顺序:
TraceId
-> 安全
-> 限流
-> 认证
-> 路由修改
-> 转发
-> 响应处理
19.5 认证与授权
常见模式:
| 模式 | 做法 |
|---|---|
| JWT | 网关验签,传递用户声明 |
| OAuth2 | 网关或资源服务器校验 token |
| Session | 网关透传 Cookie |
| API Key | 识别调用方 |
| mTLS | 服务间身份认证 |
认证后传递:
X-User-Id
X-User-Roles
X-Client-Id
X-Trace-Id
必须注意:
- 这些 Header 只能由网关注入或覆盖;
- 内部服务不能信任外部传入的伪造身份头;
- 敏感 token 不应原样写入日志;
- 授权规则要与资源绑定。
19.6 限流
限流维度:
- 全局;
- 服务;
- 路径;
- 用户;
- IP;
- 租户;
- API Key。
算法:
| 算法 | 特点 |
|---|---|
| 固定窗口 | 简单,边界突刺 |
| 滑动窗口 | 平滑,内存稍高 |
| 令牌桶 | 允许突发 |
| 漏桶 | 平滑输出 |
| 分布式 Redis + Lua | 多实例一致 |
响应:
429 Too Many Requests
Retry-After: 1
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
限流不是只给 429,还要考虑排队、优先级和降级。
19.7 超时与重试
配置:
spring:
cloud:
gateway:
httpclient:
connect-timeout: 1000
response-timeout: 5s
超时链路:
客户端超时
>= 网关总超时
> 后端服务超时
网关重试必须谨慎:
- 默认只重试幂等请求;
- POST 下单不应盲目重试;
- 有幂等键才可重试;
- 限制重试次数;
- 设置熔断保护。
19.8 灰度发布
常见策略:
| 策略 | 做法 |
|---|---|
| Header 灰度 | 指定用户或内部流量 |
| 权重灰度 | 5% 流量到新版本 |
| 租户灰度 | 指定客户先体验 |
| 地域灰度 | 某机房先发布 |
| Cookie 灰度 | 白名单用户 |
示例:
routes:
- id: order-v1
uri: lb://order-service-v1
predicates:
- Path=/api/orders/**
- Weight=order-group, 95
- id: order-v2
uri: lb://order-service-v2
predicates:
- Path=/api/orders/**
- Weight=order-group, 5
必须配套:
- 版本指标;
- 快速回滚;
- 一致性校验;
- 用户粘性;
- 业务观察窗口。
19.9 可观测性
访问日志字段:
time
remote_ip
method
path
status
bytes
request_time
upstream_service
upstream_host
upstream_status
trace_id
user_id
client_id
指标:
gateway_request_total
gateway_request_seconds
gateway_status_total
gateway_timeout_total
gateway_limit_total
gateway_upstream_seconds
gateway_active_connections
告警:
- 5xx 比例;
- P99 延迟;
- 429 增长;
- upstream timeout;
- 路由无健康实例;
- 网关内存和连接数。
19.10 高可用
部署:
DNS / SLB
-> Gateway 多实例
-> 服务多实例
要点:
- 网关无状态;
- 配置热更新可回滚;
- 后端健康检查;
- 网关 CPU 和内存充足;
- 避免阻塞调用;
- 限制请求体大小;
- 防慢连接攻击;
- TLS 证书管理;
- 压测长连接和并发;
- 定期故障演练。
本章小结
网关是流量、安全、观测和发布策略的统一边界。Spring Cloud Gateway 提供路由谓词和过滤器模型,生产中要重点治理认证头、超时、限流、重试、灰度和可观测性。网关应保持轻量、无状态和高可用,业务规则应下沉到服务内部。
思考题
- 为什么网关不适合承载复杂业务逻辑?
- 网关认证后如何安全传递用户身份?
- 限流维度如何选择?
- 哪些请求可以在网关重试?
- 灰度发布需要哪些配套能力?