全局过滤器
GlobalFilter 接口与 GatewayFilter 具有相同的签名。这些是特殊过滤器,它们有条件地应用于所有路由。
| 此接口及其用法在未来的里程碑版本中可能会有所更改。 |
组合全局过滤器和 GatewayFilter 排序
当请求匹配路由时,过滤 web 处理器会将 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.metrics.tags.path.enabled 属性(默认情况下为 false),您可以激活一个带有路径标签的额外指标
-
path:请求的路径。
这些指标随后可从 /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 写入响应过滤器
如果 ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR 交换属性中存在 Netty HttpClientResponse,则 NettyWriteResponseFilter 会运行。它在所有其他过滤器完成后运行,并将代理响应写回网关客户端响应。(还有一个实验性的 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 值会覆盖请求网关时指定的方案。例如,如果请求通过 HTTPS 进入网关,但 ServiceInstance 指示不安全,则下游请求将通过 HTTP 进行。相反的情况也可能适用。但是,如果在网关配置中为路由指定了 GATEWAY_SCHEME_PREFIX_ATTR,则前缀将被剥离,并且路由 URL 中产生的方案将覆盖 ServiceInstance 配置。 |
| Gateway 支持所有 LoadBalancer 功能。您可以在 Spring Cloud Commons 文档 中阅读更多相关内容。 |
RouteToRequestUrl 过滤器
如果 ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR 交换属性中存在 Route 对象,则 RouteToRequestUrlFilter 会运行。它创建一个新的 URI,该 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: https://:3001
predicates:
- Path=/websocket/info/**
# Normal Websocket route
- id: websocket_route
uri: ws://:3001
predicates:
- Path=/websocket/**
标记交换已路由
在网关路由 ServerWebExchange 之后,它通过向交换属性添加 gatewayAlreadyRouted 来标记该交换为“已路由”。一旦请求被标记为已路由,其他路由过滤器将不会再次路由该请求,从而跳过该过滤器。您可以使用方便的方法来标记交换已路由或检查交换是否已路由。
-
ServerWebExchangeUtils.isAlreadyRouted接受ServerWebExchange对象并检查它是否已被“路由”。 -
ServerWebExchangeUtils.setAlreadyRouted接受ServerWebExchange对象并将其标记为“已路由”。