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-store 或 private)。

它接受两个配置参数:

  • 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 过滤器 允许在路由级别使用此功能。

注意

要启用此功能,请添加 com.github.ben-manes.caffeine:caffeine 和 spring-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 具有 http 或 https 协议,则 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/**

注意

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

注意

从 ReactiveLoadBalancerClientFilter 返回的 ServiceInstance 的 isSecure 值会覆盖发往网关的请求中指定的协议。 例如,如果请求通过 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 具有 ws 或 wss 协议,则 Websocket 路由过滤器运行。它使用 Spring WebSocket 基础设施向下游转发 websocket 请求。

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

注意

如果您使用 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.