Skip to content

GatewayFilter 工厂

在微服务架构中,网关作为系统的入口点,需要对请求和响应进行各种处理,如添加请求头、修改响应状态码、限流、认证等。Spring Cloud Gateway 通过 GatewayFilter Factories 提供了强大而灵活的过滤器机制。

Route filters(路由过滤器)

允许以某种方式修改传入的 HTTP 请求或传出的 HTTP 响应。路由过滤器的作用域限定在特定的路由上。Spring Cloud Gateway 包含许多内置的 GatewayFilter 工厂。

什么是 GatewayFilter Factories?

GatewayFilter Factories 是 Spring Cloud Gateway 中用于创建过滤器的工厂类。这些工厂可以根据配置参数创建相应的过滤器实例,对请求和响应进行处理。

处理流程

核心概念

1. 过滤器类型

Spring Cloud Gateway 中的过滤器分为两大类:

  • Pre 过滤器:在请求转发到后端服务之前执行
  • Post 过滤器:在从后端服务收到响应之后执行

2. 过滤器作用域

  • Route Filter:作用于特定路由
  • Global Filter:作用于所有路由

常见过滤器

1. AddRequestHeader 过滤器

业务场景:在微服务调用链中,需要在请求头中添加用户信息、追踪 ID 等元数据。

kotlin
import org.springframework.cloud.gateway.route.RouteLocator
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class GatewayConfig {

    @Bean
    fun customRoutes(builder: RouteLocatorBuilder): RouteLocator {
        return builder.routes()
            .route("add-request-header") { r ->
                r.path("/api/users/**")
                    .filters { f ->
                        f.addRequestHeader("X-Request-Source", "Gateway") // 添加请求头
                         .addRequestHeader("X-User-Type", "Premium")      // 添加用户类型
                    }
                    .uri("http://user-service")
            }
            .build()
    }
}
yaml
# application.yml 配置方式
spring:
  cloud:
    gateway:
      routes:
        - id: add-request-header-route
          uri: http://user-service
          predicates:
            - Path=/api/users/**
          filters:
            - AddRequestHeader=X-Request-Source, Gateway
            - AddRequestHeader=X-User-Type, Premium

2. AddResponseHeader 过滤器

业务场景:为响应添加安全头、CORS 头或自定义元数据。

kotlin
@Bean
fun securityHeadersRoute(builder: RouteLocatorBuilder): RouteLocator {
    return builder.routes()
        .route("security-headers") { r ->
            r.path("/api/public/**")
                .filters { f ->
                    f.addResponseHeader("X-Frame-Options", "DENY")           // 防止点击劫持
                     .addResponseHeader("X-Content-Type-Options", "nosniff") // 防止MIME类型嗅探
                     .addResponseHeader("X-Response-Time", System.currentTimeMillis().toString()) // 响应时间戳
                }
                .uri("http://public-service")
        }
        .build()
}

3. RewritePath 过滤器

业务场景:API 版本管理,将旧版本的 API 路径重写为新版本。

kotlin
@Bean
fun pathRewriteRoute(builder: RouteLocatorBuilder): RouteLocator {
    return builder.routes()
        .route("path-rewrite") { r ->
            r.path("/v1/api/**")
                .filters { f ->
                    // 将 /v1/api/users 重写为 /v2/api/users
                    f.rewritePath("/v1/api/(?<segment>.*)", "/v2/api/\${segment}")
                }
                .uri("http://api-service")
        }
        .build()
}

4. RequestRateLimiter 过滤器

业务场景:限制 API 调用频率,防止系统过载。

kotlin
import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver
import reactor.core.publisher.Mono

@Bean
fun rateLimitRoute(builder: RouteLocatorBuilder): RouteLocator {
    return builder.routes()
        .route("rate-limit") { r ->
            r.path("/api/orders/**")
                .filters { f ->
                    f.requestRateLimiter { config ->
                        config.rateLimiter = redisRateLimiter()        // 使用Redis作为限流存储
                        config.keyResolver = userKeyResolver()         // 基于用户ID限流
                    }
                }
                .uri("http://order-service")
        }
        .build()
}

@Bean
fun redisRateLimiter(): RedisRateLimiter {
    return RedisRateLimiter(10, 20, 1) // 每秒10个请求,突发20个,每次补充1个令牌
}

@Bean
fun userKeyResolver(): KeyResolver {
    return KeyResolver { exchange ->
        // 基于用户ID进行限流
        Mono.just(exchange.request.headers.getFirst("X-User-Id") ?: "anonymous")
    }
}

5. Retry 过滤器

业务场景:在网络不稳定的环境中,自动重试失败的请求。

kotlin
@Bean
fun retryRoute(builder: RouteLocatorBuilder): RouteLocator {
    return builder.routes()
        .route("retry") { r ->
            r.path("/api/payment/**")
                .filters { f ->
                    f.retry { config ->
                        config.retries = 3                              // 重试3次
                        config.statuses = setOf(HttpStatus.BAD_GATEWAY, HttpStatus.SERVICE_UNAVAILABLE)
                        config.methods = setOf(HttpMethod.GET, HttpMethod.POST) // 只对GET和POST重试
                        config.backoff = RetryGatewayFilterFactory.BackoffConfig().apply {
                            firstBackoff = Duration.ofMillis(100)        // 首次重试间隔100ms
                            maxBackoff = Duration.ofSeconds(2)           // 最大重试间隔2s
                            factor = 2.0                                 // 指数退避因子
                        }
                    }
                }
                .uri("http://payment-service")
        }
        .build()
}

6. CircuitBreaker 过滤器

业务场景:在下游服务不可用时,快速失败并提供降级响应。

kotlin
@Bean
fun circuitBreakerRoute(builder: RouteLocatorBuilder): RouteLocator {
    return builder.routes()
        .route("circuit-breaker") { r ->
            r.path("/api/recommendations/**")
                .filters { f ->
                    f.circuitBreaker { config ->
                        config.name = "recommendationCircuitBreaker"    // 断路器名称
                        config.fallbackUri = "forward:/fallback/recommendations" // 降级URI
                    }
                }
                .uri("http://recommendation-service")
        }
        .build()
}

// 降级处理器
@RestController
class FallbackController {

    @GetMapping("/fallback/recommendations")
    fun recommendationFallback(): ResponseEntity<Map<String, Any>> {
        val fallbackResponse = mapOf(
            "message" to "推荐服务暂时不可用,为您提供默认推荐",
            "recommendations" to listOf("热门商品1", "热门商品2", "热门商品3"),
            "timestamp" to System.currentTimeMillis()
        )
        return ResponseEntity.ok(fallbackResponse)
    }
}

自定义 GatewayFilter Factory

当内置过滤器无法满足需求时,可以创建自定义的过滤器工厂。

业务场景:请求日志记录

kotlin
import org.springframework.cloud.gateway.filter.GatewayFilter
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory
import org.springframework.stereotype.Component
import reactor.core.publisher.Mono
import org.slf4j.LoggerFactory

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

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

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

            logger.info(
                "请求开始 - 方法: {}, 路径: {}, 客户端IP: {}, User-Agent: {}",
                request.method,
                request.path,
                getClientIp(exchange),
                request.headers.getFirst("User-Agent")
            )

            chain.filter(exchange).then(
                Mono.fromRunnable {
                    val endTime = System.currentTimeMillis()
                    val response = exchange.response

                    logger.info(
                        "请求完成 - 状态码: {}, 耗时: {}ms, 路径: {}",
                        response.statusCode,
                        endTime - startTime,
                        request.path
                    )
                }
            )
        }
    }

    private fun getClientIp(exchange: org.springframework.web.server.ServerWebExchange): String {
        val request = exchange.request
        return request.headers.getFirst("X-Forwarded-For")
            ?: request.headers.getFirst("X-Real-IP")
            ?: request.remoteAddress?.address?.hostAddress
            ?: "unknown"
    }

    override fun getConfigClass(): Class<Config> = Config::class.java

    class Config {
        var includeHeaders: Boolean = false      // 是否包含请求头信息
        var includeBody: Boolean = false         // 是否包含请求体信息
    }
}

使用自定义过滤器

kotlin
@Bean
fun customLoggingRoute(builder: RouteLocatorBuilder): RouteLocator {
    return builder.routes()
        .route("logging") { r ->
            r.path("/api/**")
                .filters { f ->
                    f.filter(RequestLoggingGatewayFilterFactory().apply(
                        RequestLoggingGatewayFilterFactory.Config().apply {
                            includeHeaders = true    // 包含请求头
                            includeBody = false      // 不包含请求体
                        }
                    ))
                }
                .uri("http://backend-service")
        }
        .build()
}

过滤器链执行顺序

过滤器的执行顺序可以通过 @Order 注解或实现 Ordered 接口来控制:

kotlin
@Component
@Order(-1)  // 数值越小,优先级越高
class HighPriorityFilter : GlobalFilter, Ordered {

    override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> {
        // 高优先级过滤器逻辑
        return chain.filter(exchange)
    }

    override fun getOrder(): Int = -1
}
过滤器执行顺序示意图

配置方式对比

1. YAML 配置方式

适合简单的过滤器配置,配置清晰直观

yaml
spring:
  cloud:
    gateway:
      routes:
        - id: example-route
          uri: http://example.com
          predicates:
            - Path=/api/**
          filters:
            - AddRequestHeader=X-Source, Gateway
            - AddResponseHeader=X-Powered-By, Spring Cloud Gateway
            - RewritePath=/api/(?<segment>.*), /${segment}

2. Kotlin 配置方式

适合复杂的过滤器配置,支持动态配置和条件逻辑

kotlin
@Bean
fun complexRoute(builder: RouteLocatorBuilder): RouteLocator {
    return builder.routes()
        .route { r ->
            r.path("/api/**")
                .and().header("X-User-Type", "premium")  // 条件组合
                .filters { f ->
                    f.addRequestHeader("X-Priority", "high")
                     .requestRateLimiter { config ->
                         config.rateLimiter = premiumUserRateLimiter()
                         config.keyResolver = userKeyResolver()
                     }
                }
                .uri("http://premium-service")
        }
        .build()
}

最佳实践

1. 性能优化

TIP

  • 避免在过滤器中进行阻塞操作
  • 合理设置过滤器执行顺序
  • 使用异步非阻塞的方式处理请求
kotlin
// ❌ 错误示例:阻塞操作
override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> {
    Thread.sleep(1000) // 阻塞操作,会影响性能
    return chain.filter(exchange)
}

// ✅ 正确示例:异步操作
override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> {
    return Mono.delay(Duration.ofSeconds(1))  // 非阻塞延迟
        .then(chain.filter(exchange))
}

2. 错误处理

kotlin
override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> {
    return chain.filter(exchange)
        .onErrorResume { throwable ->
            logger.error("过滤器执行异常", throwable)
            // 返回错误响应
            val response = exchange.response
            response.statusCode = HttpStatus.INTERNAL_SERVER_ERROR
            response.setComplete()
        }
}

3. 监控和观测

kotlin
@Component
class MetricsFilter : GlobalFilter {

    private val meterRegistry: MeterRegistry = Metrics.globalRegistry

    override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> {
        val timer = Timer.start(meterRegistry)

        return chain.filter(exchange)
            .doFinally {
                timer.stop(Timer.builder("gateway.request.duration")
                    .tag("path", exchange.request.path.value())
                    .tag("method", exchange.request.method.toString())
                    .register(meterRegistry))
            }
    }
}

常见问题与解决方案

1. 过滤器不生效

检查过滤器的注册和路由匹配条件

kotlin
// 确保过滤器已注册为Bean
@Component
class MyCustomFilter : GlobalFilter {
    // 实现逻辑
}

// 确保路由条件正确匹配
.route { r ->
    r.path("/api/**")  // 检查路径匹配规则
     .filters { f -> f.myCustomFilter() }
}

2. 过滤器执行顺序问题

kotlin
// 使用Order注解控制执行顺序
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)  // 最高优先级
class AuthenticationFilter : GlobalFilter

3. 内存泄漏问题

kotlin
// 正确处理资源释放
override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> {
    return chain.filter(exchange)
        .doFinally { signalType ->
            // 清理资源
            cleanup()
        }
}

总结

Spring Cloud Gateway 的 GatewayFilter Factories 提供了强大的请求和响应处理能力:

  1. 内置过滤器:涵盖了大部分常见的网关功能需求
  2. 自定义扩展:支持创建自定义过滤器满足特殊业务需求
  3. 配置灵活:支持 YAML 和代码两种配置方式
  4. 性能优秀:基于 WebFlux 的响应式编程模型,支持高并发

通过合理使用这些过滤器,可以构建出功能强大、性能优秀的微服务网关系统。