7. Global Filters
该GlobalFilter接口具有与 相同的签名GatewayFilter。这些是有条件地应用于所有路由的特殊过滤器。
此接口及其用法可能会在未来的里程碑版本中发生变化。
7.1. 组合全局过滤器和GatewayFilter排序
当请求与路由匹配时,过滤 Web 处理程序会将 的所有实例GlobalFilter和所有特定于路由的实例添加GatewayFilter到过滤器链中。这个组合的过滤器链是按org.springframework.core.Ordered接口排序的,你可以通过实现getOrder()方法来设置。
由于 Spring Cloud Gateway 区分过滤器逻辑执行的“前”和“后”阶段(请参阅如何工作),具有最高优先级的过滤器是“前”阶段的第一个和“后”阶段的最后一个 -阶段。
以下清单配置了一个过滤器链:
例 57.ExampleConfiguration.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;
}
}
7.2. 转发路由过滤器
在ForwardRoutingFilterexchange 属性中查找 URI ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR。如果 URL 有一个forward方案(例如forward:///localendpoint),它使用 SpringDispatcherHandler来处理请求。请求 URL 的路径部分被转发 URL 中的路径覆盖。未修改的原始 URL 将附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR属性中的列表中。
7.3. The ReactiveLoadBalancerClientFilter
在ReactiveLoadBalancerClientFilter名为 的交换属性中查找 URI ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR。如果 URL 有一个lb方案(例如lb://myservice),它使用 Spring CloudReactorLoadBalancer将名称(在本例中)解析为myservice实际的主机和端口,并替换同一属性中的 URI。未修改的原始 URL 将附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR属性中的列表中。过滤器还查看ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR属性以查看它是否等于lb。如果是这样,则适用相同的规则。以下清单配置了一个ReactiveLoadBalancerClientFilter:
示例 58.application.yml
spring:
cloud:
gateway:
routes:
- id: myRoute
uri: lb://service
predicates:
- Path=/service/**
默认情况下,当 找不到服务实例时ReactorLoadBalancer,503返回 a。404您可以通过设置将网关配置为返回spring.cloud.gateway.loadbalancer.use404=true。
从返回 的isSecure值覆盖向网关发出的请求中指定的方案。例如,如果请求通过网关进入,但指示它不安全,则发出下游请求。相反的情况也可以适用。但是,如果在网关配置中为路由指定了前缀,则会去除前缀,并且路由 URL 的结果方案会覆盖配置。 ServiceInstanceReactiveLoadBalancerClientFilterHTTPSServiceInstanceHTTPGATEWAY_SCHEME_PREFIX_ATTRServiceInstance
Gateway 支持所有 LoadBalancer 功能。您可以在Spring Cloud Commons 文档中阅读有关它们的更多信息。
7.4. Netty 路由过滤器
如果位于ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR交换属性中的 URL 具有httporhttps方案,则 Netty 路由过滤器运行。它使用 NettyHttpClient发出下游代理请求。响应被放入ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR交换属性中,以供稍后的过滤器使用。(还有一个WebClientHttpRoutingFilter执行相同功能但不需要 Netty 的实验。)
7.5. Netty 写响应过滤器
如果交换属性中NettyWriteResponseFilter有 Netty HttpClientResponse,则运行。ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR它在所有其他过滤器完成后运行,并将代理响应写回网关客户端响应。(还有一个WebClientWriteResponseFilter执行相同功能但不需要 Netty 的实验。)
7.6. RouteToRequestUrl过滤器
如果交换属性中有Route对象,则运行。它基于请求 URI 创建一个新的 URI,但使用对象的 URI 属性进行更新。新的 URI 被放置在exchange 属性中。ServerWebExchangeUtils.GATEWAY_ROUTE_ATTRRouteToRequestUrlFilterRouteServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
如果 URI 具有方案前缀,例如lb:ws://serviceid,lb则从 URI 中剥离方案并放置在ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR过滤器链中以供稍后使用。
7.7. Websocket 路由过滤器
如果位于ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTRexchange 属性中的 URL 具有wsorwss方案,则 websocket 路由过滤器运行。它使用 Spring WebSocket 基础设施向下游转发 websocket 请求。
您可以通过在 URI 前加上前缀来负载平衡 websocket lb,例如lb:ws://serviceid.
如果你使用SockJS作为普通 HTTP 的后备,你应该配置一个普通的 HTTP 路由以及 websocket 路由。
以下清单配置了一个 websocket 路由过滤器:
示例 59.application.yml
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/**
7.8. 网关指标过滤器
要启用网关指标,请将 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为项目依赖项。
7.9. 将交换标记为已路由
网关路由 a 后,它通过添加 交换属性将该交换ServerWebExchange标记为“已路由” 。gatewayAlreadyRouted一旦请求被标记为已路由,其他路由过滤器将不会再次路由该请求,实质上是跳过过滤器。您可以使用一些便捷的方法将交换标记为已路由或检查交换是否已被路由。
-
ServerWebExchangeUtils.isAlreadyRouted获取一个ServerWebExchange对象并检查它是否已被“路由”。
-
ServerWebExchangeUtils.setAlreadyRouted获取一个ServerWebExchange对象并将其标记为“已路由”。