跳到主要内容
版本:5.0.1

全局过滤器

DeepSeek V3 中英对照 Global Filters

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

备注

此接口及其使用方式在未来的里程碑版本中可能会发生变化。

全局过滤器与 GatewayFilter 的组合排序​

当一个请求匹配到路由时,过滤网络处理器会将所有 GlobalFilter 实例以及所有路由特定的 GatewayFilter 实例添加到一个过滤器链中。这个组合后的过滤器链会按照 org.springframework.core.Ordered 接口进行排序,你可以通过实现 getOrder() 方法来设置排序顺序。

由于 Spring Cloud Gateway 在过滤器逻辑执行上区分“pre”和“post”两个阶段(参见工作原理),优先级最高的过滤器在“pre”阶段最先执行,在“post”阶段最后执行。

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

@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;
}
}

网关指标过滤器​

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

  • routeId: 路由ID。

  • routeUri: API路由到的URI。

  • outcome: 结果,由 HttpStatus.Series 分类。

  • status: 返回给客户端的请求HTTP状态。

  • httpStatusCode: 返回给客户端的请求HTTP状态码。

  • httpMethod: 请求使用的HTTP方法。

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

  • path: 请求的路径。
注意

属性 spring.cloud.gateway.server.webflux.metrics.tags.path.enabled 同样会添加上述指标,但会产生将值作为标签的副作用。此属性已被弃用,并将在未来的版本中移除。

这些指标随后可以从 /actuator/metrics/spring.cloud.gateway.requests 端点抓取,并能轻松与 Prometheus 集成,以创建 Grafana 仪表板。您还可以利用这些有用的指标进行告警,具体示例可参考 告警模板。

备注

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

本地响应缓存过滤器​

如果启用了相关属性,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 表示小时)。

如果这些参数均未配置但启用了全局过滤器,默认情况下,它会为缓存的响应配置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 进行注入。

转发路由过滤器​

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

Netty 路由过滤器​

当 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 交换属性中的 URL 具有 http 或 https 方案时,Netty 路由过滤器会运行。它使用 Netty 的 HttpClient 来发起下游代理请求。响应被放入 ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR 交换属性中,供后续过滤器使用。(还有一个实验性的 WebClientHttpRoutingFilter 执行相同的功能,但不需要 Netty。)

Netty 写响应过滤器​

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

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:

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

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

备注

从 ReactiveLoadBalancerClientFilter 返回的 ServiceInstance 的 isSecure 值会覆盖向 Gateway 发出的请求中指定的方案。例如,如果请求通过 HTTPS 进入 Gateway,但 ServiceInstance 指示其不安全,则下游请求将通过 HTTP 发出。相反的情况也可能适用。但是,如果在 Gateway 配置中为路由指定了 GATEWAY_SCHEME_PREFIX_ATTR,则会剥离前缀,并且路由 URL 生成的方案会覆盖 ServiceInstance 配置。

提示

Gateway 支持所有 LoadBalancer 的功能。你可以在 Spring Cloud Commons 文档 中了解更多相关信息。

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 中,以便在过滤器链的后续步骤中使用。

Websocket 路由过滤器​

如果 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 交换属性中的 URL 具有 ws 或 wss 方案,则 WebSocket 路由过滤器会运行。它使用 Spring WebSocket 基础设施将 WebSocket 请求转发到下游。

您可以通过在URI前添加lb前缀来实现WebSocket的负载均衡,例如lb:ws://serviceid。

备注

如果你使用 SockJS 作为普通 HTTP 的降级方案,你应该同时配置一个普通的 HTTP 路由以及 WebSocket 路由。

以下配置了一个 WebSocket 路由过滤器:

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/**

将交换标记为已路由​

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

  • ServerWebExchangeUtils.isAlreadyRouted 接收一个 ServerWebExchange 对象,并检查其是否已被“路由”。

  • ServerWebExchangeUtils.setAlreadyRouted 接收一个 ServerWebExchange 对象,并将其标记为“已路由”。