Skip to content

Spring Cloud Gateway 工作原理详解

以下图表展示了 Spring Cloud Gateway 的高级工作流程:

详细工作步骤

  1. 请求接收:客户端向 Spring Cloud Gateway 发送请求
  2. 路由匹配:Gateway Handler Mapping 判断请求是否匹配某个路由规则
  3. 处理器分发:如果匹配成功,请求被发送到 Gateway Web Handler
  4. 过滤器链执行:处理器通过特定于该请求的过滤器链运行请求
  5. 代理转发:执行所有"pre"过滤器逻辑后,发出代理请求
  6. 响应处理:代理请求完成后,运行"post"过滤器逻辑

过滤器工作机制

Spring Cloud Gateway 的过滤器分为两个阶段:

Pre 过滤器

  • 在代理请求发送之前执行
  • 用于请求预处理,如:
    • 请求验证和认证
    • 请求头添加或修改
    • 限流控制
    • 请求日志记录

Post 过滤器

  • 在代理请求之后执行
  • 用于响应后处理,如:
    • 响应头添加或修改
    • 响应内容转换
    • 监控指标收集
    • 响应日志记录

过滤器被虚线分隔的原因是它们可以在代理请求发送前后运行逻辑,这种设计使得网关具有强大的请求和响应处理能力。

实际业务场景应用

Details

场景一:微服务 API 统一入口

kotlin
@Component
class CustomGatewayFilterFactory : AbstractGatewayFilterFactory<CustomGatewayFilterFactory.Config>() {

    override fun apply(config: Config): GatewayFilter {
        return GatewayFilter { exchange, chain ->
            val request = exchange.request
            val response = exchange.response

            // Pre 过滤器逻辑:添加请求头
            val modifiedRequest = request.mutate()
                .header("X-Request-Time", System.currentTimeMillis().toString())
                .header("X-Request-ID", UUID.randomUUID().toString())
                .build()

            val modifiedExchange = exchange.mutate()
                .request(modifiedRequest)
                .build()

            // 继续过滤器链
            chain.filter(modifiedExchange).then(Mono.fromRunnable {
                // Post 过滤器逻辑:添加响应头
                response.headers.add("X-Response-Time", System.currentTimeMillis().toString())
                response.headers.add("X-Gateway", "Spring-Cloud-Gateway")
            })
        }
    }

    // 配置类
    class Config {
        // 过滤器配置参数
    }
}
Details

场景二:路由配置示例

kotlin
@Configuration
class GatewayConfig {

    @Bean
    fun routeLocator(builder: RouteLocatorBuilder): RouteLocator {
        return builder.routes()
            // 用户服务路由
            .route("user-service") { predicateSpec ->
                predicateSpec
                    .path("/api/users/**")  // 路径匹配
                    .and()
                    .method(HttpMethod.GET, HttpMethod.POST)  // 方法匹配
                    .filters { filterSpec ->
                        filterSpec
                            .stripPrefix(1)  // 去除路径前缀
                            .addRequestHeader("X-Service", "user-service")  // 添加请求头
                            .circuitBreaker { config ->  // 熔断器
                                config.name = "user-service-cb"
                                config.fallbackUri = "forward:/fallback/user"
                            }
                    }
                    .uri("lb://user-service")  // 负载均衡到用户服务
            }
            // 订单服务路由
            .route("order-service") { predicateSpec ->
                predicateSpec
                    .path("/api/orders/**")
                    .and()
                    .header("Authorization")  // 需要认证头
                    .filters { filterSpec ->
                        filterSpec
                            .stripPrefix(1)
                            .addRequestHeader("X-Service", "order-service")
                            .requestRateLimiter { config ->  // 限流
                                config.rateLimiter = RedisRateLimiter(10, 20)
                                config.keyResolver = { exchange ->
                                    Mono.just(exchange.request.remoteAddress?.address?.hostAddress ?: "unknown")
                                }
                            }
                    }
                    .uri("lb://order-service")
            }
            .build()
    }

    // 自定义键解析器用于限流
    @Bean
    @Primary
    fun remoteAddrKeyResolver(): KeyResolver {
        return KeyResolver { exchange ->
            Mono.just(exchange.request.remoteAddress?.address?.hostAddress ?: "unknown")
        }
    }
}
yaml
spring:
  cloud:
    gateway:
      routes:
        # 用户服务路由配置
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/users/**
            - Method=GET,POST
          filters:
            - StripPrefix=1
            - AddRequestHeader=X-Service, user-service
            - name: CircuitBreaker
              args:
                name: user-service-cb
                fallbackUri: forward:/fallback/user

        # 订单服务路由配置
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/orders/**
            - Header=Authorization
          filters:
            - StripPrefix=1
            - AddRequestHeader=X-Service, order-service
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10
                redis-rate-limiter.burstCapacity: 20
                key-resolver: "#{@remoteAddrKeyResolver}"

      # 全局过滤器配置
      default-filters:
        - AddResponseHeader=X-Gateway, Spring-Cloud-Gateway
        - AddResponseHeader=X-Response-Time, #{T(System).currentTimeMillis()}

核心概念解析

1. Route(路由)

路由是网关的基本构建块,由以下组件组成:

  • ID:路由的唯一标识符
  • 目标 URI:请求转发的目标地址
  • 断言集合:匹配 HTTP 请求的条件
  • 过滤器集合:对匹配的请求进行修改

2. Predicate(断言)

用于匹配 HTTP 请求的任何内容,如请求头、参数、路径等。

3. Filter(过滤器)

在发送下游请求之前或之后修改请求和响应。

重要配置说明

URI 默认端口说明:

  • HTTP 协议的默认端口是 80
  • HTTPS 协议的默认端口是 443
  • 如果路由中未指定端口,将使用对应协议的默认端口

路由 URI 中定义的任何路径都将被忽略。例如:`uri: http://example.com/some/path` 中的 `/some/path` 部分会被忽略。

性能优化建议

1. 过滤器优化

kotlin
@Component
@Order(-100)  // 设置过滤器执行顺序
class PerformanceFilter : GlobalFilter {

    private val logger = LoggerFactory.getLogger(PerformanceFilter::class.java)

    override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> {
        val startTime = System.currentTimeMillis()

        return chain.filter(exchange).doFinally { signalType ->
            val endTime = System.currentTimeMillis()
            val duration = endTime - startTime

            // 记录请求处理时间
            logger.info("请求 ${exchange.request.path} 处理耗时: ${duration}ms")

            // 添加性能指标到响应头
            exchange.response.headers.add("X-Response-Time", duration.toString())
        }
    }
}

2. 连接池配置

kotlin
@Configuration
class NettyConfiguration {

    @Bean
    fun httpClient(): HttpClient {
        val connectionProvider = ConnectionProvider.builder("custom")
            .maxConnections(1000)  // 最大连接数
            .maxIdleTime(Duration.ofSeconds(20))  // 最大空闲时间
            .maxLifeTime(Duration.ofSeconds(60))  // 最大生存时间
            .pendingAcquireTimeout(Duration.ofSeconds(60))  // 获取连接超时时间
            .evictInBackground(Duration.ofSeconds(120))  // 后台清理间隔
            .build()

        return HttpClient.create(connectionProvider)
            .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000)  // 连接超时
            .responseTimeout(Duration.ofSeconds(10))  // 响应超时
            .doOnConnected { conn ->
                conn.addHandlerLast(ReadTimeoutHandler(10))  // 读取超时
                    .addHandlerLast(WriteTimeoutHandler(10))  // 写入超时
            }
    }
}

常见问题和解决方案

问题 1:路由不匹配

症状:请求返回 404 错误 解决方案

  1. 检查断言配置是否正确
  2. 验证路径匹配规则
  3. 确认服务注册状态

问题 2:请求超时

症状:网关返回超时错误 解决方案

kotlin
spring:
  cloud:
    gateway:
      httpclient:
        connect-timeout: 10000  # 连接超时 10
        response-timeout: 30s   # 响应超时 30
      routes:
        - id: timeout-config
          uri: lb://slow-service
          predicates:
            - Path=/api/slow/**
          filters:
            - name: Hystrix
              args:
                name: slow-service-hystrix
                fallbackUri: forward:/fallback/timeout

监控和调试

启用 Actuator 监控

kotlin
// 添加依赖
dependencies {
    implementation("org.springframework.boot:spring-boot-starter-actuator")
}

// 配置监控端点
management:
  endpoints:
    web:
      exposure:
        include: gateway, health, info, metrics
  endpoint:
    gateway:
      enabled: true

调试过滤器

kotlin
@Component
class DebugFilter : GlobalFilter, Ordered {

    private val logger = LoggerFactory.getLogger(DebugFilter::class.java)

    override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> {
        val request = exchange.request

        logger.debug("请求路径: ${request.path}")
        logger.debug("请求方法: ${request.method}")
        logger.debug("请求头: ${request.headers}")
        logger.debug("查询参数: ${request.queryParams}")

        return chain.filter(exchange)
    }

    override fun getOrder(): Int = -1  // 优先级最高
}

总结

Spring Cloud Gateway 通过其优雅的过滤器设计和强大的路由匹配能力,为微服务架构提供了一个高性能、可扩展的 API 网关解决方案。其核心工作原理简单明了:

  1. 接收请求路由匹配过滤器处理代理转发响应返回
  2. 过滤器的 Pre 和 Post 执行机制为请求和响应处理提供了极大的灵活性
  3. 丰富的断言和过滤器工厂满足了大部分业务场景的需求

在实际项目中,建议结合具体业务需求选择合适的过滤器和路由策略,并通过监控和日志来优化网关性能。