Spring Cloud Gateway 深度解析
深入理解Gateway的请求处理流程、内置过滤器的执行顺序、与Zuul的性能对比,以及在生产环境中的高可用部署方案。
1. 核心架构与请求处理流程
1.1 为什么选择Spring Cloud Gateway
Spring Cloud Gateway基于Spring WebFlux构建,采用事件驱动模型(Event-Driven),完全异步非阻塞。相比Zuul 1.x的线程池模型,Gateway在高并发下内存占用更低、吞吐量更高。
1.2 关键组件
Gateway由四个核心组件构成:
// 1. RouteLocator - 路由定位
// 负责将请求的URL匹配到具体的路由配置
public interface RouteLocator {
Flux<Route> getRoutes();
}
// 2. Route - 路由实体
// 包含 id, uri, predicates, filters
public class Route {
private String id;
private URI uri; // 目标URI
private List<Predicate> predicates; // 谓词
private List<GatewayFilter> filters; // 过滤器
}
// 3. GatewayPredicate - 谓词
// 决定请求是否匹配某个路由
public interface GatewayPredicate {
boolean test(ServerWebExchange exchange);
}
// 4. GatewayFilter - 过滤器
// 在请求/响应链中修改数据
public interface GatewayFilter extends Shortcut {
Mono<Void> filter(ServerWebExchange exchange,
GatewayFilterChain chain);
}
1.3 请求处理流程
当请求到达Gateway时,经过以下处理步骤:
// 1. DispatcherHandler 接收请求
// 2. RoutePredicateHandlerMapping 匹配路由
// 3. FilteringWebHandler 构建过滤器链
// 4. 执行 Pre Filter(前置过滤器)
// 5. 调用后端服务
// 6. 执行 Post Filter(后置过滤器)
// 过滤器链执行顺序
// 请求: Header → Auth → RateLimit → (Backend) → Metrics → Header
// ↓ ↓ ↓ ↓ ↓
// Pre Pre Pre ... Post Post
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
// === Pre Filter ===
doPreProcessing(request);
// === 调用 chain.filter() 触发后续过滤器 ===
// 最后一个过滤器会发送请求到后端
return chain.filter(exchange)
.then(Mono.fromRunnable(() -> {
// === Post Filter ===
doPostProcessing(exchange.getResponse());
}));
}
过滤器链采用责任链模式,每个过滤器决定是否继续执行链。Pre过滤器先执行,Post过滤器后执行(类似AOP的@Before和@After)。理解这个顺序对于调试和排障至关重要。
2. 路由配置详解
2.1 基础路由配置
Gateway支持YAML和Java DSL两种配置方式:
# application.yml
spring:
cloud:
gateway:
routes:
- id: user-service
uri: http://user-service:8080
predicates:
- Path=/api/user/**
- Method=GET,POST
- Header=X-Request-Id, \d+
filters:
- StripPrefix=1
- AddRequestHeader=X-Gateway, gateway
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/order/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 100
redis-rate-limiter.burstCapacity: 200
2.2 Java DSL配置
对于复杂的路由逻辑,推荐使用Java DSL:
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("user-service", r -> r
.path("/api/user/**")
.filters(f -> f
.stripPrefix(1)
.addRequestHeader("X-Gateway", "gateway")
.retry()
.retries(3)
.series(ServerHttpStatus.INTERNAL_SERVER_ERROR)
)
.uri("lb://user-service")
)
.route("order-service", r -> r
.path("/api/order/**")
.filters(f -> f
.requestRateLimiter()
.configure(c -> c
.setRateLimiter(RedisRateLimiter.builder()
.build())
)
)
.uri("lb://order-service")
)
.build();
}
}
2.3 常用Predicate
Predicate用于匹配请求条件:
// Path Predicate - 路径匹配
.predicates(p -> p.path("/api/user/**"))
// Method Predicate - HTTP方法
.predicates(p -> p.method(HttpMethod.GET))
// Header Predicate - 请求头
.predicates(p -> p.header("X-Request-Id", "\\d+"))
// Query Predicate - 查询参数
.predicates(p -> p.query("status", "active"))
// Cookie Predicate
.predicates(p -> p.cookie("session", ".*sessionid.*"))
// RemoteAddr Predicate - 客户端IP
.predicates(p -> p.remoteAddr("192.168.1.0/24"))
// After Predicate - 时间窗口
.predicates(p -> p.after(ZonedDateTime.parse("2026-01-01T00:00:00Z")))
// 组合多个Predicate(AND关系)
// 请求必须同时满足所有条件
3. 内置过滤器详解
3.1 请求修改类过滤器
// StripPrefix - 去除URL前缀
// /api/user/123 -> /user/123 (去除第一层路径)
.filters(f -> f.stripPrefix(1))
// AddRequestHeader - 添加请求头
.filters(f -> f.addRequestHeader("X-Request-Id", UUID.randomUUID().toString()))
// AddRequestParameter - 添加查询参数
.filters(f -> f.addRequestParameter("source", "gateway"))
// SetRequestHeader - 修改请求头(覆盖)
.filters(f -> f.setRequestHeader("X-Forwarded-For", "真实的IP"))
// RemoveRequestHeader - 删除请求头
.filters(f -> f.removeRequestHeader("X-Internal-Secret"))
// SetPath - 修改请求路径
.filters(f -> f.setPath("/new/path"))
3.2 响应修改类过滤器
// AddResponseHeader - 添加响应头
.filters(f -> f.addResponseHeader("X-Gateway-Version", "1.0"))
// RemoveResponseHeader - 删除响应头
.filters(f -> f.removeResponseHeader("X-Powered-By"))
// SetResponseHeader - 修改响应头
.filters(f -> f.setResponseHeader("Cache-Control", "max-age=3600"))
3.3 限流过滤器
Gateway集成Redis实现分布式限流:
// 限流算法:令牌桶算法
// replenishRate: 每秒补充的令牌数
// burstCapacity: 桶的容量(最大突发流量)
# application.yml
spring:
cloud:
gateway:
routes:
- id: rate-limited-route
uri: lb://backend-service
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 100 # 100 req/s
redis-rate-limiter.burstCapacity: 200 # 最大200
redis-rate-limiter.requestedTokens: 1
// 自定义 KeyResolver 实现细粒度限流
@Bean
public KeyResolver apiKeyResolver() {
// 按用户ID限流
return exchange -> Mono.just(
exchange.getRequest().getHeaders()
.getFirst("X-User-Id")
);
}
// 或按IP限流
@Bean
public KeyResolver ipKeyResolver() {
return exchange -> Mono.just(
exchange.getRequest().getRemoteAddress()
.getAddress().getHostAddress()
);
}
3.4 熔断过滤器
Gateway与Spring Cloud CircuitBreaker集成,实现熔断降级:
// 1. 添加依赖
// spring-cloud-starter-circuitbreaker-reactor-resilience4j
// 2. 配置CircuitBreaker
@Bean
public Customizer<ReactiveResilience4JCircuitBreakerFactory> circuitBreakerConfig() {
return factory -> factory.configureDefault(id ->
new Resilience4JConfigBuilder(id)
.circuitBreakerConfig(CircuitBreakerConfig.custom()
.slidingWindowSize(10)
.failureRateThreshold(50)
.waitDurationInOpenState(Duration.ofSeconds(10))
.build())
.build())
);
}
// 3. 使用熔断过滤器
.routes(r -> r.path("/api/**")
.filters(f -> f
.circuitBreaker(c -> c
.setName("backend-cb")
.setFallbackUri("forward:/fallback")
)
)
.uri("lb://backend-service")
)
// 4. 编写降级方法
@GetMapping("/fallback")
public Mono<Map<String, Object>> fallback() {
return Mono.just(
Map.of("code", 503, "message", "Service temporarily unavailable")
);
}
4. Gateway vs Zuul vs Nginx
| 维度 | Spring Cloud Gateway | Zuul 1.x | Nginx |
|---|---|---|---|
| 架构模型 | 异步非阻塞(WebFlux) | 同步阻塞(Tomcat线程池) | 事件驱动(C语言) |
| 并发模型 | 单线程 + 事件循环 | 线程池(每请求一线程) | worker进程 |
| 吞吐量 | 高(低内存占用) | 中等 | 最高 |
| 编程能力 | Java DSL + Filter | Filter(受限) | Lua脚本 |
| 服务发现 | 原生集成 Eureka/Consul | Ribbon集成 | 需要额外配置 |
| 限流熔断 | Redis + Resilience4j | 需自行集成 | limit_req模块 |
| 适用场景 | 微服务网关 | 简单代理 | 入口网关+静态资源 |
Gateway与Nginx的组合使用:在K8s环境中,Nginx作为K8s Ingress Controller处理七层流量,Gateway作为微服务网关处理服务发现、熔断、限流等功能。两者配合可以发挥各自优势。
5. 生产环境最佳实践
5.1 高可用部署
Gateway应该部署多个实例,配合K8s Service或负载均衡器:
# gateway-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: gateway
spec:
replicas: 3
selector:
matchLabels:
app: gateway
template:
metadata:
labels:
app: gateway
spec:
containers:
- name: gateway
image: gateway:1.0
ports:
- containerPort: 8080
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
env:
- name: SPRING_CLOUD_GATEWAY_STREAMING_MAX_CONCURRENCY
value: "256"
---
apiVersion: v1
kind: Service
metadata:
name: gateway-svc
spec:
selector:
app: gateway
ports:
- port: 80
targetPort: 8080
type: LoadBalancer
5.2 性能调优参数
# application.yml
spring:
cloud:
gateway:
# 全局CORS配置
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "https://example.com"
allowedMethods: GET,POST,PUT,DELETE
allowedHeaders: "*"
allowCredentials: true
maxAge: 3600
# HTTP客户端配置
httpclient:
pool:
type: FIXED
maxConnections: 1000
acquireTimeout: 30s
connect-timeout: 10s
response-timeout: 30s
# Resilience4j 熔断配置
resilience4j:
circuitbreaker:
configs:
default:
slidingWindowSize: 100
minimumNumberOfCalls: 50
failureRateThreshold: 50
waitDurationInOpenState: 60s
permittedNumberOfCallsInHalfOpenState: 10
# Redis 限流配置
spring:
redis:
timeout: 2000ms
lettuce:
pool:
max-active: 50
max-idle: 10
min-idle: 5
✅ 推荐做法
- 使用lb://前缀实现负载均衡
- 配置合理的超时和重试策略
- 启用请求限流保护后端服务
- 使用health-check端点监控
❌ 避免做法
- 在Filter中执行同步阻塞操作
- 不设置超时就调用外部服务
- 使用过大的regex predicate
- 忽略CORS配置导致跨域问题