文章目录
- 核心概念
- 1 断言
- (1)AfterRoutePredicateFactory
- (2)BeforeRoutePredicateFactory
- (3)BetweenRoutePredicateFactory
- (4)MethodRoutePredicateFactory
- (5)CookieRoutePredicateFactory
- (6)HostRoutePredicateFactory
- (7)HeaderRoutePredicateFactory
- (8)PathRoutePredicateFactory
- (9)WeightRoutePredicateFactory
- (10)RemoteAddrRoutePredicateFactory
- (11)QueryRoutePredicateFactory
- (12)CloudFoundryRouteServiceRoutePredicateFactory
- (13)组合断言
- 2 过滤器
- 3 过滤器的顺序
- 参考文章
核心概念
- 路由(Route):路由是网关的基本构件。它由ID、目标URI、一组断言和一组过滤器组成。如果断言为真,则匹配该路由。gateway使用类RouteDefinition表示路由定义。
- 断言(Predicate):参照Java8的新特性Predicate。Predicate接受一个输入参数,返回一个布尔值结果,输入参数可以是HTTP请求的任何部分,比如报文头、参数、报文体,而且还可以将多个断言组合在一起。
- 过滤器(Filter):可以在发送到目标URI之前或之后修改请求和响应。
1 断言
spring cloud gateway 2.2.9.RELEASE版本里面,提供了12个断言,gateway使用工厂模式创建这些断言,它们都是在断言工厂里面创建的。这些断言工厂都继承了抽象类AfterRoutePredicateFactory。下面分别介绍这些断言的作用和例子。
(1)AfterRoutePredicateFactory
该断言支持设置一个时间,转发请求时,如果在该时间之后,则断言为真。
spring:
application:
name: gateway-demo
cloud:
gateway:
routes:
- id: route-demo
uri: http://localhost:8079
predicates:
- After=2021-09-10T00:00:00+08:00
这个断言会在东8区的2021-09-10 凌晨12点之后,将请求都转跳到http://localhost:8079。
(2)BeforeRoutePredicateFactory
与AfterRoutePredicateFactory相反,BeforeRoutePredicateFactory表示在指定的时间之前的请求都进行跳转。
spring:
application:
name: gateway-demo
cloud:
gateway:
routes:
- id: route-demo
uri: http://localhost:8079
predicates:
- Before=2021-09-10T00:00:00+08:00
这个断言会在东8区的2021-09-10 凌晨12点之前,将请求都转跳到http://localhost:8079。
(3)BetweenRoutePredicateFactory
BetweenRoutePredicateFactory接受两个时间,它表示转发在指定时间之间的请求。比如:
spring:
application:
name: gateway-demo
cloud:
gateway:
routes:
- id: route-demo
uri: http://localhost:8079
predicates:
- Between=2021-09-01T10:00:00+08:00,2021-09-10T12:00:00+08:00 # 匹配两个时间之间
(4)MethodRoutePredicateFactory
MethodRoutePredicateFactory根据POST、GET、PUT、DELETE 等不同的HTTP方法进行判断。
spring:
application:
name: gateway-demo
cloud:
gateway:
routes:
- id: route-demo
uri: http://localhost:8079
predicates:
- Method=GET
上面例子中,所有的GET请求都会被转发。Method可以指定多个。
(5)CookieRoutePredicateFactory
CookieRoutePredicateFactory根据cookie内容进行判断。它有两个参数,一个是cookie名,另一个是value,value使用正则表达式,当cookie中含有指定的cookie名,且值符合value的正则表达式,则将转发请求。
spring:
application:
name: gateway-demo
cloud:
gateway:
routes:
- id: route-demo
uri: http://localhost:8079
predicates:
- Cookie=sessionId, test
当cookie中含有sessionId=test的内容时,转发请求。
(6)HostRoutePredicateFactory
HostRoutePredicateFactory使用一组主机列表作为判断条件。如果当前请求的报文头中含有属性“Host”,且其值在指定的主机列表里面,则将转发请求。主机列表使用Ant style匹配。
spring:
application:
name: gateway-demo
cloud:
gateway:
routes:
- id: route-demo
uri: http://localhost:8079
predicates:
- Host=**.maven.org,**.spring.org
(7)HeaderRoutePredicateFactory
HeaderRoutePredicateFactory指定了两个参数,一个header的name,一个是正则匹配的value。
spring:
application:
name: gateway-demo
cloud:
gateway:
routes:
- id: route-demo
uri: http://localhost:8079
predicates:
- Header=X-Request-Id, \d+
上述规则匹配header中存在名为X-Request-Id,内容为数字的请求。
(8)PathRoutePredicateFactory
PathRoutePredicateFactory使用Spring的PathPattern匹配请求path。PathPattern支持多种规则,可以使用类似Ant style,也可以使用正则表达式,具体的规则在PathPattern类中有详细说明。
spring:
application:
name: gateway-demo
cloud:
gateway:
routes:
- id: route-demo
uri: http://localhost:8079
predicates:
- Path=/demo/**
上述规则匹配所有以/demo/开头的路径。
(9)WeightRoutePredicateFactory
WeightRoutePredicateFactory基于权重进行路由,配置时指定分组和权重值。下面网页对于配置规则及算法进行了详细说明:
https://www.cnblogs.com/liukaifeng/p/10055866.html
(10)RemoteAddrRoutePredicateFactory
RemoteAddrRoutePredicateFactory可以指定被请求的远程地址,当地址符合要求时,请求才会转发。可以在地址里面指定子网掩码。
spring:
application:
name: gateway-demo
cloud:
gateway:
routes:
- id: route-demo
uri: http://localhost:8079
predicates:
- RemoteAddr=192.168.1.1/24
上述例子中,子网掩码是24,凡是请求的远程地址为192.168.1.XXX都会被转发。
(11)QueryRoutePredicateFactory
QueryRoutePredicateFactory入参也是两个参数,一个是请求参数的属性名,另一个是属性值,属性值使用正则表达式。
spring:
application:
name: gateway-demo
cloud:
gateway:
routes:
- id: route-demo
uri: http://localhost:8079
predicates:
- Query=role,ba.
(12)CloudFoundryRouteServiceRoutePredicateFactory
CloudFoundryRouteServiceRoutePredicateFactory在云计算场景下使用。它判断header里面是否有属性:X-CF-Forwarded-Url、X-CF-Proxy-Signature和X-CF-Proxy-Metadata。当header里面同时有上述三个属性时,请求才会被转发。
spring:
application:
name: gateway-demo
cloud:
gateway:
routes:
- id: route-demo
uri: http://localhost:8079
predicates:
- CloudFoundry=XXX
CloudFoundry的值对请求转发不起作用,可以随意写任何值。
(13)组合断言
我们可以组合上面介绍的断言一起使用。比如:
spring:
application:
name: gateway-demo
cloud:
gateway:
routes:
- id: route-demo
uri: http://localhost:8079
predicates:
- Path=/demo/**
- Query=role,ba.
- After=2021-09-10T00:00:00+08:00
当所有的断言都为真时,请求才会被转发。
2 过滤器
过滤器可以修改HTTP请求的输入和输出,Spring Cloud Gateway内置了很多不同功能的过滤器。在gateway中,过滤器有两个顶级接口,这也将过滤器分为两类:
- GatewayFilter:网关过滤器,需要通过
spring.cloud.routes.filters
配置在具体路由下,只作用在当前路由上或通过spring.cloud.default-filters
配置在全局,作用在所有路由上。 - GlobalFilter:全局过滤器,不需要在配置文件中配置,作用在所有的路由上,最终通过
GatewayFilterAdapter
包装成GatewayFilterChain
可识别的过滤器。
gateway提供了很多过滤器,本文只介绍部分过滤器介绍。网关过滤器使用了工厂模式,均是由对应的工厂类创建,工厂类都实现自GatewayFilterFactory接口。
2.1 网关过滤器
(1)AddRequestHeaderGatewayFilterFactory
AddRequestHeaderGatewayFilterFactory可以在header里面增加指定的name和value。比如:
spring:
cloud:
gateway:
routes:
- id: route-demo
uri: http://localhost:8079
filters:
- AddRequestHeader=X-Request,BAR
对被转发的请求,会在header里面额外添加属性值X-Request=Bar。
(2)AddResponseHeaderGatewayFilterFactory
AddResponseHeaderGatewayFilterFactory在请求响应的header里面添加指定的name和value。比如:
spring:
cloud:
gateway:
routes:
- id: route-demo
uri: http://localhost:8079
filters:
- AddResponseHeader=X-Request,BAR
当收到响应后,在header里面增加属性值X-Request=Bar。
(3)RemoveRequestHeaderGatewayFilterFactory
RemoveRequestHeaderGatewayFilterFactory在header里面删除指定的name。
(4)MapRequestHeaderGatewayFilterFactory
MapRequestHeaderGatewayFilterFactory指定两个header的属性名:fromHeader和toHeader,转发请求前,过滤器将属性名从fromHeader替换为toHeader,属性值不变。
(5)RewritePathGatewayFilterFactory
RewritePathGatewayFilterFactory可以对请求路径重写。过滤器指定两个参数:regexp和replacement,两个参数都使用正则表达式,前者指定要替换的内容,后者表示被替换后的内容。
spring:
cloud:
gateway:
routes:
- id: route-demo
uri: http://localhost:8079
predicates:
- Path=/foo/**
filters:
- RewritePath=/foo/(?<segment>.*), /$\{segment}
对于上面的例子,如果请求的路径是/foo/bar,则gateway会将请求路径改为/bar发送给下游。
(6)PrefixPathGatewayFilterFactory
该过滤器工厂为匹配的URI添加指定前缀。
(7)AddRequestParameter
该过滤器将指定参数添加请求中。
还有其他过滤器,本文不再介绍。请参见文章:
https://blog.csdn.net/abu935009066/article/details/112252692
2.2 全局过滤器
全局过滤器实现了Order接口,该接口的作用用于指定过滤器的顺序,数字越小,优先级越高。
(1)NettyWriteResponseFilter
使用Netty与请求方建立的连接将收到的代理响应写回请求端。
(2)GatewayMetricsFilter
该过滤器用于监控,提供监控指标。它统计请求成功、失败的次数,请求耗时时长等。
该过滤器需要依赖spring-boot-starter-actuator。
(3)NoLoadBalancerClientFilter
该过滤器要求目标URI的schema不能是“lb
”,否则向请求方返回404。
lb表示从注册中心获取目标URL。
如果要使该过滤器失效,则需要引入Ribbon。
(4)WebClientWriteResponseFilter
使用WebClient与请求方建立的连接将收到的代理响应写回请求端。
(5)WebClientHttpRoutingFilter
使用WebClient向目标URI发送http
和https
请求。不过在发送前,要先经过gateway中的其他过滤器处理,在所有的过滤器都处理完毕后,再发送请求。
(6)ForwardRoutingFilter
ForwardRoutingFilter会查看客户端请求的URI的schema是否是forward
,比如:forward://localendpoint,如果是,则它会使用Spring的DispatcherHandler
来处理这个请求。
(7)ForwardPathFilter
ForwardPathFilter会查看目标URI的scheme是否是forward
,比如:forward://localendpoint
,如果是,则它会使用Spring的DispatcherHandler
来处理这个请求。
(8)RouteToRequestUrlFilter
这个过滤器用于将从request里获取的原始URL转换成Gateway转发时所使用的URL。
如果 URL 具有 scheme 前缀,例如 lb:ws://serviceid
,该 lb scheme将从URL中剥离,并放到Gateway上下文中,方便后面的过滤器使用。
(9)ReactiveLoadBalancerClientFilter
该过滤器依赖spring-cloud-starter-loadbalancer
。
如果原始URL或者目标URL的scheme为“lb
”,比如:lb://myservice
,那么ReactiveLoadBalancerClientFilter使用ReactorLoadBalancer查找myservice的服务地址列表,并且使用负载均衡算法选择合适的地址。
(10)NettyRoutingFilter
使用Netty的HttpClient
向目标URI发送http
和https
请求。不过在发送前,要先经过gateway中的其他过滤器处理,在所有的过滤器都处理完毕后,再发送请求。
(11)WebsocketRoutingFilter
使用WebSocketService向目标URI发送ws
和wss
请求。
3 过滤器的顺序
当请求到来时,gateway添加所有GlobalFilter实例和匹配的GatewayFilter实例到过滤器链中,通过对filter bean配置注解@Order
,过滤器链会对这些过滤器实例进行排序。
Spring Cloud Gateway将过滤器的逻辑按请求执行点分为”pre
”和”post
”的一前一后处理,如果是高优先级的过滤器,则在”pre
”逻辑中最先执行,在”post
”逻辑中最后执行。
参考文章
https://docs.spring.io/spring-cloud-gateway/docs/2.2.9.RELEASE/reference/html