Skip to content

全局过滤器 (Global Filters)

GlobalFilter 接口具有与 GatewayFilter 相同的签名。 这些是特殊的过滤器,会有条件地应用于所有路由。

注意

此接口及其用法可能会在未来的里程碑版本中更改。

1. 全局过滤器与 GatewayFilter 的组合顺序

当请求匹配到路由时,过滤 Web 处理程序会将所有 GlobalFilter 实例和所有特定于路由的 GatewayFilter 实例添加到过滤器链中。 这个组合的过滤器链是根据 org.springframework.core.Ordered 接口排序的,你可以通过实现 getOrder() 方法来设置优先级。

由于 Spring Cloud Gateway 将过滤器逻辑执行区分为“pre”(前置)和“post”(后置)阶段(参见 工作原理),因此优先级最高(Numerical Value 最小)的过滤器在“pre”阶段第一个执行,而在“post”阶段最后一个执行。

以下示例配置了一个过滤器链:

ExampleConfiguration.java

java
@Bean
public GlobalFilter customFilter() {
    return new CustomGlobalFilter();
}

public class CustomGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("custom global filter");
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -1;
    }
}

2. Gateway Metrics 过滤器 (监控指标)

要启用网关指标,请添加 spring-boot-starter-actuator 作为项目依赖项。然后,默认情况下,只要 spring.cloud.gateway.metrics.enabled 属性未设置为 false,网关指标过滤器就会运行。 此过滤器会添加一个名为 spring.cloud.gateway.requests 的 Timer 指标,并包含以下标签(Tags):

  • routeId:路由 ID。
  • routeUri:API 路由到的目标 URI。
  • outcome:结果分类,由 HttpStatus.Series 定义。
  • status:返回给客户端的 HTTP 状态码。
  • httpStatusCode:返回给客户端的 HTTP 状态码。
  • httpMethod:请求使用的 HTTP 方法。

此外,通过 spring.cloud.gateway.metrics.tags.path.enabled 属性(默认为 false),您可以激活带有路径标签的额外指标:

  • path:请求的路径。

这些指标可以从 /actuator/metrics/spring.cloud.gateway.requests 抓取,并且可以轻松地与 Prometheus 集成以创建 Grafana 仪表板。 您还可以使用这些有用的指标进行报警。

注意

要启用 prometheus 端点,请添加 micrometer-registry-prometheus 作为项目依赖项。

3. Local Response Cache 过滤器 (本地响应缓存)

如果启用了相关属性,LocalResponseCache 将运行:

  • spring.cloud.gateway.global-filter.local-response-cache.enabled:为所有路由激活全局缓存。
  • spring.cloud.gateway.filter.local-response-cache.enabled:激活在路由级别使用的关联过滤器。

此功能使用 Caffeine 为满足以下条件的所有响应启用本地缓存:

  • 无请求体的 GET 请求。
  • 响应具有以下状态码之一:HTTP 200 (OK)、HTTP 206 (Partial Content) 或 HTTP 301 (Moved Permanently)。
  • HTTP Cache-Control 头允许缓存(即请求中没有 no-store,响应中没有 no-storeprivate)。

它接受两个配置参数:

  • spring.cloud.gateway.filter.local-response-cache.size:设置此路由缓存条目的最大大小(单位:KB, MB, GB)。
  • spring.cloud.gateway.filter.local-response-cache.time-to-live:设置缓存条目的过期时间(单位:s 秒, m 分, h 小时)。

如果未配置这些参数但启用了全局过滤器,则默认情况下,缓存响应的生存时间(TTL)为 5 分钟。

此过滤器还实现了 HTTP Cache-Control 头中 max-age 值的自动计算。 如果原始响应中存在 max-age,则该值将被重写为 timeToLive 配置参数中设置的秒数。 在后续调用中,此值将根据响应过期的剩余秒数重新计算。

spring.cloud.gateway.global-filter.local-response-cache.enabled 设置为 false 会停用所有路由的本地响应缓存,但 LocalResponseCache 过滤器 允许在路由级别使用此功能。

::: note 注意 要启用此功能,请添加 com.github.ben-manes.caffeine:caffeinespring-boot-starter-cache 作为项目依赖项。 :::

警告

如果您的项目创建了自定义 CacheManager Bean,则需要将其标记为 @Primary 或使用 @Qualifier 注入。

4. Forward Routing 过滤器

ForwardRoutingFilter 在交换属性 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 中查找 URI。 如果 URL 具有 forward 协议(例如 forward:///localendpoint),它将使用 Spring DispatcherHandler 来处理请求。 请求 URL 的路径部分将被 forward URL 中的路径覆盖。 未修改的原始 URL 将追加到 ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR 属性的列表中。

5. Netty Routing 过滤器

如果位于 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 交换属性中的 URL 具有 httphttps 协议,则 Netty路由过滤器运行。 它使用 Netty HttpClient 发起下游代理请求。 响应被放入 ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR 交换属性中,以供后续过滤器使用。 (还有一个实验性的 WebClientHttpRoutingFilter 执行相同的功能,但不需要 Netty。)

6. Netty Write Response 过滤器

如果 ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR 交换属性中存在 Netty HttpClientResponse,则 NettyWriteResponseFilter 运行。 它在所有其他过滤器完成后运行,并将代理响应写回网关客户端响应。 (还有一个实验性的 WebClientWriteResponseFilter 执行相同的功能,但不需要 Netty。)

7. ReactiveLoadBalancerClientFilter

ReactiveLoadBalancerClientFilter 在名为 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 的交换属性中查找 URI。 如果 URL 具有 lb 协议(例如 lb://myservice),它使用 Spring Cloud ReactorLoadBalancer 将名称(本例中为 myservice)解析为实际的主机和端口,并替换同一属性中的 URI。 未修改的原始 URL 将追加到 ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR 属性的列表中。 该过滤器还会查看 ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR 属性,看它是否等于 lb。如果是,则适用相同的规则。

以下示例配置了一个 ReactiveLoadBalancerClientFilter

application.yml

yaml
spring:
  cloud:
    gateway:
      routes:
      - id: myRoute
        uri: lb://service
        predicates:
        - Path=/service/**

::: note 注意 默认情况下,当 ReactorLoadBalancer 找不到服务实例时,会返回 503。 您可以配置网关通过设置 spring.cloud.gateway.loadbalancer.use404=true 来返回 404。 :::

::: note 注意 从 ReactiveLoadBalancerClientFilter 返回的 ServiceInstanceisSecure 值会覆盖发往网关的请求中指定的协议。 例如,如果请求通过 HTTPS 进入网关,但 ServiceInstance 指示它不安全,则下游请求将通过 HTTP 发出。反之亦然。 但是,如果在网关配置中为路由指定了 GATEWAY_SCHEME_PREFIX_ATTR,则前缀将被剥离,并且路由 URL 中的协议将覆盖 ServiceInstance 配置。 :::

提示

Gateway 支持所有 LoadBalancer 功能。您可以在 Spring Cloud Commons 文档 中阅读有关它们的更多信息。

8. RouteToRequestUrl 过滤器

如果 ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR 交换属性中存在 Route 对象,则 RouteToRequestUrlFilter 运行。 它根据请求 URI 创建一个新的 URI,但使用 Route 对象的 URI 属性进行更新。 新 URI 被放置在 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 交换属性中。

如果 URI 具有协议前缀,例如 lb:ws://serviceid,则 lb 协议将从 URI 中剥离,并放置在 ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR 中,以供过滤器链后续使用。

9. Websocket Routing 过滤器

如果位于 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 交换属性中的 URL 具有 wswss 协议,则 Websocket 路由过滤器运行。它使用 Spring WebSocket 基础设施向下游转发 websocket 请求。

您可以通过在 URI 前加上 lb 来对 websockets 进行负载均衡,例如 lb:ws://serviceid

::: note 注意 如果您使用 SockJS 作为普通 HTTP 的 fallback,则应配置普通 HTTP 路由以及 websocket 路由。 :::

以下示例配置了一个 websocket 路由过滤器:

application.yml

yaml
spring:
  cloud:
    gateway:
      routes:
      # SockJS route
      - id: websocket_sockjs_route
        uri: http://localhost:3001
        predicates:
        - Path=/websocket/info/**
      # Normal Websocket route
      - id: websocket_route
        uri: ws://localhost:3001
        predicates:
        - Path=/websocket/**

10. 将 Exchange 标记为已路由 (Marking An Exchange As Routed)

网关路由 ServerWebExchange 后,它会通过将 gatewayAlreadyRouted 添加到交换属性来将该交换标记为“已路由”。 一旦请求被标记为已路由,其他路由过滤器将不会再次路由该请求,本质上是跳过该过滤器。 您可以使用便捷方法将交换标记为已路由或检查交换是否已被路由。

  • ServerWebExchangeUtils.isAlreadyRouted 接受一个 ServerWebExchange 对象并检查它是否已被“路由”。
  • ServerWebExchangeUtils.setAlreadyRouted 接受一个 ServerWebExchange 对象并将其标记为“已路由”。

Based on Spring Framework.