📅 2026-05-19 👤 陈磊 🏷️ Spring Cloud · 网关 · 反应式

Spring Cloud Gateway 深度解析

深入理解Gateway的请求处理流程、内置过滤器的执行顺序、与Zuul的性能对比,以及在生产环境中的高可用部署方案。

1. 核心架构与请求处理流程

1.1 为什么选择Spring Cloud Gateway

Spring Cloud Gateway基于Spring WebFlux构建,采用事件驱动模型(Event-Driven),完全异步非阻塞。相比Zuul 1.x的线程池模型,Gateway在高并发下内存占用更低、吞吐量更高。

Client 请求
HandlerMapping
WebHandler
Filter Chain
Route
Backend

1.2 关键组件

Gateway由四个核心组件构成:

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两种配置方式:

YAML 路由配置
# 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:

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用于匹配请求条件:

常用 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实现分布式限流:

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或负载均衡器:

K8s 部署配置
# 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 性能调优参数

Gateway 性能调优
# 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配置导致跨域问题