全局过滤器
GlobalFilter
接口具有与 GatewayFilter
相同的签名。这些是特殊过滤器,有条件地应用于所有路由。
此接口及其用法可能会在未来的里程碑版本中更改。 |
全局过滤器和 GatewayFilter
的组合排序
当请求匹配到某个路由时,过滤 web 处理器会将 GlobalFilter
的所有实例和路由特定的 GatewayFilter
所有实例添加到过滤器链中。这个组合的过滤器链通过 org.springframework.core.Ordered
接口进行排序,你可以通过实现 getOrder()
方法来设置排序。
Spring Cloud Gateway 在过滤器逻辑执行时区分“前置(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 进行注入。 |
Forward 路由过滤器
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 值会覆盖发送到网关的请求中指定的方案(scheme)。例如,如果请求通过 HTTPS 进入网关,但 `ServiceInstance` 表明它不安全,则下游请求会通过 HTTP 发起。反之亦然。但是,如果在网关配置中为路由指定了 GATEWAY_SCHEME_PREFIX_ATTR ,则会剥离前缀,并且路由 URL 中产生的方案会覆盖 ServiceInstance 配置。 |
网关支持所有 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
,则会从 URI 中剥离 lb
方案,并将其放置在 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
对象,并将其标记为“已路由”。