GlobalFilter接口具有与GatewayFilter相同的签名。这些是有条件地应用于所有路由的特殊过滤器。
组合GlobalFilter和GatewayFilter
当请求与路由匹配时,过滤web处理程序会将GlobalFilter的所有实例和GatewayFilter的所有路由特定实例添加到过滤器链中。这个组合的过滤器链由org.springframework.core.Ordered接口排序。由于Spring Cloud Gateway区分了过滤器逻辑执行的“前”和“后”阶段,因此优先级最高的过滤器是“前”阶段的第一个执行,也是“后”相位的最后一个执行。
@Component
public class CustomGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("custom global filter");
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -1;
}
}
要自定义全局过滤器,实现GlobalFilter并交给Spring管理即可。
1、Forward Routing Filter
ForwardRoutingFilter在交换属性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR中查找URI。如果URL具有转发方案(例如forward:///localendpoint),它使用Spring DispatcherHandler来处理该请求。请求URL的路径部分被转发URL中的路径覆盖。未修改的原始URL将附加到ServerWebExchangeUtils.GATEWAY_original_REQUEST_URL_ATTR属性中的列表中。
2、ReactiveLoadBalancerClientFilter
ReactiveLoadBalancerClientFilter在名为ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR的交换属性中查找URI。如果URL具有lb方案(如lb://myservice),它将使用Spring Cloud ReactorLoadBalancer将名称解析为实际主机和端口,并替换同一属性中的URI。未修改的原始URL将附加到ServerWebExchangeUtils.GATEWAY_original_REQUEST_URL_ATTR属性中的列表中。该筛选器还会在ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR属性中查找它是否等于lb。如果是,则适用相同的规则。
3、 Netty Routing Filter
如果ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR交换属性中的URL具有http或https方案,则运行Netty路由过滤器。它使用Netty HttpClient来进行下游代理请求。响应被放入ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR交换属性中,以便在以后的过滤器中使用。
4、Netty Write Response Filter
如果ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR交换属性中存在Netty HttpClientResponse,则运行NettyWriteResponseFilter。它在所有其他过滤器完成后运行,并将代理响应写回网关客户端响应。
5、RouteToRequestUrl Filter
如果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中,以便稍后在过滤器链中使用。
6、Websocket Routing Filter
如果位于ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR交换属性中的URL具有ws或wss方案,则会运行websocket路由筛选器。它使用Spring WebSocket基础结构将WebSocket请求转发到下游。可以通过在URI前面加lb来实现websocket的负载平衡,例如lb:ws://serviceid。
7、Gateway Metrics Filter
要启用网关指标,请添加spring-boot-starter-actuator作为项目依赖项。然后,默认情况下,只要属性spring.cloud.gateway.metrics.enabled未设置为false,网关度量过滤器就会运行。此筛选器添加一个名为spring.cloud.gateway.requests的计时器度量,该度量具有以下标记:
- routeId:路由ID。
- routeUri:API路由到的URI。
- output:结果,按HttpStatus.Series分类。
- status:返回到客户端的请求的HTTP状态。
- httpStatusCode:返回到客户端的请求的HTTP状态。
- httpMethod:用于请求的HTTP方法。
此外,通过属性spring.cloud.gateway.metrics.tags.path.enabled(默认情况下,设置为false),可以使用标记激活额外的度量:
- path:请求的路径。
然后,可以从/executor/metrics/spring.cloud.gateway.requests中抓取这些指标,并可以轻松地与Prometheus集成以创建Grafana仪表板。
GatewayServer模块添加依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
在application.yml配置:
management:
endpoints:
web:
exposure:
include: '*'
spring:
cloud:
gateway:
enabled: true
routes:
- id: Goods-Server # 路由 id,唯一标识
uri: lb://producer
predicates:
# - Path=/** # 断言,路由匹配条件,匹配 /product 开头的所有 api
- Path=/producer/{segment}
filters:
- StripPrefix=1
metrics:
tags:
path:
enabled: true
enabled: true
management.endpoints.web.exposure.include开启actuator端点。访问http://localhost:8500/actuator/metrics/spring.cloud.gateway.requests:
{
"name": "spring.cloud.gateway.requests",
"description": null,
"baseUnit": "seconds",
"measurements": [
{
"statistic": "COUNT",
"value": 1.0
},
{
"statistic": "TOTAL_TIME",
"value": 0.175096068
},
{
"statistic": "MAX",
"value": 0.175096068
}
],
"availableTags": [
{
"tag": "routeUri",
"values": [
"lb://producer"
]
},
{
"tag": "path",
"values": [
"/producer/{segment}"
]
},
{
"tag": "path.enabled",
"values": [
"true"
]
},
{
"tag": "routeId",
"values": [
"Goods-Server"
]
},
{
"tag": "httpMethod",
"values": [
"GET"
]
},
{
"tag": "outcome",
"values": [
"SUCCESSFUL"
]
},
{
"tag": "status",
"values": [
"OK"
]
},
{
"tag": "httpStatusCode",
"values": [
"200"
]
}
]
}
将Exchange标记为已路由
网关路由ServerWebExchange后,通过将gatewayAlreadyRouted添加到交换属性,将该交换标记为“已路由”。一旦一个请求被标记为已路由,其他路由过滤器就不会再次路由该请求,基本上跳过了过滤器。可以使用一些方便的方法将交换标记为已路由,或检查交换是否已路由。
- ServerWebExchangeUtils.isAlreadyRouted获取ServerWebExchange对象并检查该对象是否已“路由”。
- ServerWebExchangeUtils.setAlreadyRouted获取ServerWebExchange对象并将其标记为“已路由”。