一 什么是全局过滤器
首先,我们要知道全局过滤器其实是特殊路由过滤器(特殊的GatewayFilter),会有条件地作用于所有路由。
为什么要自定义全局过滤器?就好比是看大门的保安大叔,平时主要是做好进出大门外来人员登记即可,但是因为新冠疫情,现在还需要给外来人员测量体温等等。而已有的全局过滤器就好比是登记操作,而自定义的全局过滤器就好比是测量体温操作,是结合具体场景添加的。
比如以下两个场景:
- 权限校验 - 通过全局过滤器校验权限资源
- 统一对请求或响应信息做处理
工作原理:
当请求与路由匹配时,过滤WebHandler会将GlobalFilter的所有实例和GatewayFilter的所有特定于路由的实例添加到过滤器链中。该组合的过滤器链由org.springframework.core.Ordered接口排序,您可以通过实现getOrder()方法进行设置。
由于Spring Cloud Gateway区分了过滤器逻辑执行的“前”阶段和“后”阶段,因此具有最高优先级的过滤器在“前”阶段中是第一个,在“后”阶段中是最后一个。
二 自带的全局过滤器包含哪些
要自定义全局过滤,首先我们应该去了解一下gateway自带的主要的全局过滤器有哪些,并了解他们的作用。
ForwardRoutingFilter
ForwardRoutingFilter在exchange属性
ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
中查找URI。如果URL具有转发scheme(例如forward:/// localendpoint
),则它将使用Spring DispatcherHandler来处理请求。请求URL的路径部分被转发URL中的路径覆盖。未经修改的原始URL会附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR
属性中的列表中。LoadBalancerClientFilter
LoadBalancerClientFilter在
ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR的exchange
属性中查找URI。如果URL的方案为lb(例如lb:// myservice
),它将使用Spring Cloud LoadBalancerClient将名称(在本例中为myservice)解析为实际的主机和端口,并替换同一属性中的URI。未经修改的原始URL会附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR
属性中的列表中。过滤器还会在ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR
属性中查找其是否等于lb。如果是,则适用相同的规则。下面的清单配置一个LoadBalancerClientFilter:1
2
3
4
5
6
7
8spring:
cloud:
gateway:
routes:
- id: myRoute
uri: lb://service
predicates:
- Path=/service/**注意1:默认情况下,当在LoadBalancer中找不到服务实例时,将返回503。您可以通过设置
spring.cloud.gateway.loadbalancer.use404 = true
将网关配置为返回404。注意2:从LoadBalancer返回的ServiceInstance的isSecure值将覆盖对网关的请求中指定的方案。例如,如果请求通过HTTPS进入网关,但是ServiceInstance指示它不安全,则下游请求通过HTTP发出。相反的情况也可以适用。但是,如果在网关配置中为路由指定了GATEWAY_SCHEME_PREFIX_ATTR,则会删除前缀,并且路由URL产生的方案将覆盖ServiceInstance配置。
注意3:LoadBalancerClientFilter在默认情况下使用阻塞的LoadBalancerClient。建议改用ReactiveLoadBalancerClientFilter。可以通过将
spring.cloud.loadbalancer.ribbon.enabled
的值设置为false来切换到该值。ReactiveLoadBalancerClientFilter
ReactiveLoadBalancerClientFilter与上面的LoadBalancerClientFilter类似,差异主要是ReactiveLoadBalancerClientFilter是非阻塞的。
注意1:与LoadBalancerClientFilter一样,默认情况下,当ReactorLoadBalancer无法找到服务实例时,将返回503。您可以通过设置spring.cloud.gateway.loadbalancer.use404 = true将网关配置为返回404。
NettyRoutingFilter
如果
ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
的exchange属性中的URL带有http或https,则将运行NettyRoutingFilter。它使用Netty HttpClient发出下游代理请求。响应将放入ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR的exchange
属性中,供后面的过滤器使用。 (还有一个实验性的WebClientHttpRoutingFilter,它执行相同的功能,但不需要Netty。)经过该过滤器时,会通过ServerWebExchangeUtils.setAlreadyRouted方法把exchange对象标记为“已路由”。
RouteToRequestUrlFilter
如果
ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR
的exchange属性中存在Route对象,则RouteToRequestUrlFilter将运行。它基于请求URI创建一个新URI,但使用Route对象的URI属性进行更新。新的URI放置在ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
的exchange属性中。如果URI具有scheme前缀(例如
lb:ws://serviceid
),则将从URI中剥离lb方案,并将其放在ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR中,以供后面在过滤器链中使用。WebsocketRoutingFilter
顾名思义,WebsocketRoutingFilter过滤器是用于处理websocket请求的,如果ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR的exchange属性中的URL具有ws或wss的schema,则将运行WebsocketRoutingFilter。它使用Spring WebSocket基础结构向下游转发websocket请求。
您可以通过为URI加上lb前缀来平衡websocket的负载,例如
lb:ws://serviceid
经过该过滤器时,会通过ServerWebExchangeUtils.setAlreadyRouted方法把exchange对象标记为“已路由”。
配置示例如下,通常情况下,除了配置ws,还需要配置一个http的,因为发起websocket连接的请求是http请求。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15# 官方示例
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/**GatewayMetricsFilter
该过滤器主要用于做网关度量监控的,要启用,需添加
spring-boot-starter-actuator
依赖。然后,默认情况下,只要属性spring.cloud.gateway.metrics.enabled
未设置为false,GatewayMetricsFilter
就会运行。此过滤器添加一个带有以下标记的计时器度量标准,名为gateway.requests:routeId
: 路由ID.routeUri
: 需要路由的APIoutcome
: 结果分类参考 HttpStatus.Series.status
: 返回给客户端的http statushttpStatusCode
: 返回给客户端的http statushttpMethod
: 用户请求的http Method
这些指标随后可从
/actuator/metrics/gateway.requests
中进行抓取,并可轻松地与Prometheus集成以创建Grafana dashboard。要启用prometheus端点,请添加micrometer-registry-prometheus依赖。
三 如何自定义全局过滤器
方式一如下:
1 | package com.qicoder.gateway.filter; |
方式二如下:
1 |
|