Skip to content

Spring Cloud Gateway 默认过滤器

概述

Spring Cloud Gateway 的默认过滤器(Default Filters)是一种强大的机制,允许开发者为所有路由统一应用某些过滤器逻辑。通过配置 spring.cloud.gateway.default-filters 属性,可以避免在每个路由中重复配置相同的过滤器,大大简化了网关的配置和维护工作。

默认过滤器会自动应用到网关中的所有路由,无需在每个路由中单独配置,这是与路由级过滤器的主要区别。

业务场景

在实际的微服务架构中,我们经常需要对所有通过网关的请求执行一些通用操作,例如:

  • 安全增强:为所有响应添加安全相关的头部信息
  • 请求追踪:添加全局的请求 ID 或追踪标识
  • API 版本管理:为所有 API 请求添加统一的路径前缀
  • 监控统计:记录所有请求的基本信息
  • CORS 处理:统一处理跨域请求

真实案例:电商平台 API 网关

假设我们正在开发一个电商平台,有以下微服务:

  • 用户服务 (user-service)
  • 商品服务 (product-service)
  • 订单服务 (order-service)
  • 支付服务 (payment-service)

我们需要为所有这些服务的 API 响应添加统一的标识头部,并为所有请求添加 API 版本前缀。

配置方式

YAML 配置

yaml
spring:
  cloud:
    gateway:
      default-filters:
        # 为所有响应添加自定义头部,标识这是来自电商平台的响应
        - AddResponseHeader=X-Platform-Source, E-Commerce-Gateway
        # 为所有请求添加API版本前缀
        - PrefixPath=/api/v1
        # 添加请求处理时间头部
        - AddResponseHeader=X-Response-Time, #{T(java.time.Instant).now()}

Kotlin 编程式配置

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 customRouteLocator(builder: RouteLocatorBuilder): RouteLocator {
        return builder.routes()
            .route("user-service-route") { r ->
                r.path("/users/**")
                    .uri("http://localhost:8081")
            }
            .route("product-service-route") { r ->
                r.path("/products/**")
                    .uri("http://localhost:8082")
            }
            .route("order-service-route") { r ->
                r.path("/orders/**")
                    .uri("http://localhost:8083")
            }
            .build()
    }

    /**
     * 自定义全局过滤器 - 更高级的默认过滤器实现
     * 这个过滤器会自动应用到所有路由
     */
    @Bean
    fun customGlobalFilter(): GlobalFilter {
        return GlobalFilter { exchange, chain ->
            // 记录请求开始时间
            val startTime = System.currentTimeMillis()

            return@GlobalFilter chain.filter(exchange).then(
                Mono.fromRunnable {
                    // 计算请求处理时间
                    val duration = System.currentTimeMillis() - startTime

                    // 添加响应头部
                    exchange.response.headers.add("X-Response-Time", "${duration}ms")
                    exchange.response.headers.add("X-Platform-Source", "E-Commerce-Gateway")

                    // 记录日志
                    val request = exchange.request
                    println("请求路径: ${request.path}, 处理时间: ${duration}ms")
                }
            )
        }
    }
}
java
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
public class GatewayConfig {

    /**
     * 编程式配置默认过滤器
     * 这种方式提供了更灵活的配置选项
     */
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
            .route("user-service-route", r ->
                r.path("/users/**")
                 .uri("http://localhost:8081"))
            .route("product-service-route", r ->
                r.path("/products/**")
                 .uri("http://localhost:8082"))
            .route("order-service-route", r ->
                r.path("/orders/**")
                 .uri("http://localhost:8083"))
            .build();
    }

    /**
     * 自定义全局过滤器 - 更高级的默认过滤器实现
     * 这个过滤器会自动应用到所有路由
     */
    @Bean
    public GlobalFilter customGlobalFilter() {
        return (exchange, chain) -> {
            // 记录请求开始时间
            long startTime = System.currentTimeMillis();

            return chain.filter(exchange).then(
                Mono.fromRunnable(() -> {
                    // 计算请求处理时间
                    long duration = System.currentTimeMillis() - startTime;

                    // 添加响应头部
                    exchange.getResponse().getHeaders().add("X-Response-Time", duration + "ms");
                    exchange.getResponse().getHeaders().add("X-Platform-Source", "E-Commerce-Gateway");

                    // 记录日志
                    ServerHttpRequest request = exchange.getRequest();
                    System.out.println("请求路径: " + request.getPath() + ", 处理时间: " + duration + "ms");
                })
            );
        };
    }
}

工作流程

常用的默认过滤器类型

1. 响应头部处理

kotlin
// application.yml 配置
spring:
  cloud:
    gateway:
      default-filters:
        # 添加安全相关头部
        - AddResponseHeader=X-Content-Type-Options, nosniff
        - AddResponseHeader=X-Frame-Options, DENY
        - AddResponseHeader=X-XSS-Protection, 1; mode=block
        # 添加CORS支持
        - AddResponseHeader=Access-Control-Allow-Origin, *
        - AddResponseHeader=Access-Control-Allow-Methods, GET,POST,PUT,DELETE

2. 请求路径处理

kotlin
// 为所有路由添加API版本前缀
spring:
  cloud:
    gateway:
      default-filters:
        - PrefixPath=/api/v1
        # 原始请求: /users/123
        # 转发请求: /api/v1/users/123

3. 请求限流

kotlin
// 全局限流配置
spring:
  cloud:
    gateway:
      default-filters:
        - name: RequestRateLimiter
          args:
            redis-rate-limiter.replenishRate: 10  # 每秒允许的请求数
            redis-rate-limiter.burstCapacity: 20  # 令牌桶容量
            key-resolver: "#{@ipKeyResolver}"     # 限流键解析器

高级应用场景

自定义默认过滤器工厂

kotlin
import org.springframework.cloud.gateway.filter.GatewayFilter
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory
import org.springframework.stereotype.Component

/**
 * 自定义的默认过滤器工厂
 * 用于添加平台标识和追踪信息
 */
@Component
class PlatformTrackingGatewayFilterFactory :
    AbstractGatewayFilterFactory<PlatformTrackingGatewayFilterFactory.Config>() {

    data class Config(
        var platformName: String = "default",
        var environment: String = "production"
    )

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

            // 生成唯一的追踪ID
            val traceId = generateTraceId()

            // 在请求中添加追踪信息
            val modifiedRequest = request.mutate()
                .header("X-Trace-ID", traceId)
                .header("X-Platform", config.platformName)
                .build()

            // 在响应中添加平台信息
            response.headers.add("X-Platform-Name", config.platformName)
            response.headers.add("X-Environment", config.environment)
            response.headers.add("X-Trace-ID", traceId)

            // 记录请求日志
            logRequest(request, traceId)

            chain.filter(exchange.mutate().request(modifiedRequest).build())
        }
    }

    /**
     * 生成唯一的追踪ID
     */
    private fun generateTraceId(): String {
        return "${System.currentTimeMillis()}-${(1000..9999).random()}"
    }

    /**
     * 记录请求日志
     */
    private fun logRequest(request: ServerHttpRequest, traceId: String) {
        println("🚀 [${traceId}] ${request.method} ${request.path} from ${request.remoteAddress}")
    }

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

配置使用自定义过滤器

yaml
spring:
  cloud:
    gateway:
      default-filters:
        - name: PlatformTracking
          args:
            platform-name: E-Commerce-Platform
            environment: production
        - AddResponseHeader=X-API-Version, v1.0.0
        - PrefixPath=/api

与路由级过滤器的对比

特性默认过滤器路由级过滤器
作用范围所有路由指定路由
配置位置default-filters路由定义中的 filters
使用场景通用逻辑处理特定路由的定制化处理
优先级较高较低
维护成本低(一次配置)高(每个路由都需配置)

在实际项目中,建议将通用的处理逻辑(如安全头部、追踪信息)配置为默认过滤器,将特定业务逻辑配置为路由级过滤器。

最佳实践

1. 性能优化

kotlin
/**
 * 高性能的默认过滤器实现
 * 避免在过滤器中进行耗时操作
 */
@Component
class PerformantGlobalFilter : GlobalFilter, Ordered {

    // 使用缓存避免重复计算
    private val headerCache = ConcurrentHashMap<String, String>()

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

        return chain.filter(exchange)
            .doFinally {
                // 异步记录性能指标,避免阻塞请求处理
                recordMetrics(exchange, startTime)
            }
    }

    private fun recordMetrics(exchange: ServerWebExchange, startTime: Long) {
        val duration = (System.nanoTime() - startTime) / 1_000_000 // 转换为毫秒
        // 这里可以集成监控系统,如 Micrometer
        println("请求处理时间: ${duration}ms")
    }

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

2. 错误处理

kotlin
/**
 * 带有错误处理的默认过滤器
 */
@Component
class RobustGlobalFilter : GlobalFilter {

    override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> {
        return chain.filter(exchange)
            .onErrorResume { throwable ->
                // 记录错误但不中断请求流
                handleError(exchange, throwable)
                chain.filter(exchange)
            }
    }

    private fun handleError(exchange: ServerWebExchange, error: Throwable) {
        // 添加错误标识头部
        exchange.response.headers.add("X-Gateway-Error", "true")

        // 记录错误日志
        println("网关处理错误: ${error.message}")

        // 可以集成错误监控系统
        // errorReportingService.report(error, exchange)
    }
}

总结

Spring Cloud Gateway 的默认过滤器机制为微服务架构提供了强大而灵活的横切关注点处理能力。通过合理配置默认过滤器,我们可以:

  • 🎯 统一管理:集中处理所有路由的通用逻辑
  • 提升性能:避免重复的过滤器配置和执行
  • 🔧 简化维护:减少配置文件的复杂度
  • 🛡️ 增强安全:统一应用安全策略
  • 📊 监控追踪:实现全局的请求监控和追踪

使用默认过滤器时要注意性能影响,避免在过滤器中执行耗时操作,特别是同步 I/O 操作,这可能会影响整个网关的吞吐量。

通过结合配置文件声明式配置和编程式配置,我们可以构建出既灵活又高效的 API 网关解决方案。