写在前面 本文参考以下文章,请参考原文
springcloud(十五):服务网关 Spring Cloud GateWay 入门
Predicate & Spring Cloud Gateway 路由匹配规则
Predicate 来源于 Java 8,是 Java 8 中引入的一个函数,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。可以用于接口请求参数校验、判断新老数据是否有变化需要进行更新操作。
在 Spring Cloud Gateway 中 Spring 利用 Predicate 的特性实现了各种路由匹配规则,有通过 Header、请求参数等不同的条件来进行作为条件匹配到对应的路由。
在Spring Cloud Gateway--网关路由 简单示例了Spring Cloud Gateway的路由功能,现在讲一下Spring Cloud Gateway的路由规则。
1.通过时间匹配(datetime)
通过配置predicated 的 Before ,After ,Between 等属性,可以实现限制路由转发的时间段。时间对比:Spring 是通过 ZonedDateTime 来对时间进行的对比,ZonedDateTime 是 Java 8 中日期时间功能里,用于表示带时区的日期与时间信息的类,ZonedDateTime 支持通过时区来设置时间,中国的时区是:Asia/Shanghai
- Before Route Predicate 刚好相反,在某个时间之前的请求的请求都进行转发
- After Route Predicate 是指在这个时间之后的请求都转发到目标地址
- Between Route Predicate 只有在这段时间内的请求才进行转发
在Spring Cloud Gateway--网关路由 的例子基础上修改application.yml如下,就表示在这个时间之前可以进行路由,在这时间之后停止路由,修改完之后重启项重新启动网关服务,访问http://localhost:8080/discoveryClient,页面会报 404 没有找到地址
server: port: 8080 spring: cloud: gateway: routes: - id: neo_route uri: http://localhost:2001/ predicates: - Path=/discoveryClient - Before=2020-12-01T06:06:06+08:00[Asia/Shanghai]
修改application.yml如下,就表示在这个时间之后的时间可以进行路由,修改完之后重启项重新启动网关服务,访问http://localhost:8080/discoveryClient,会自动路由到 http://localhost:2001/discoveryClient
server: port: 8080 spring: cloud: gateway: routes: - id: neo_route uri: http://localhost:2001/ predicates: - Path=/discoveryClient - After=2020-21-01T06:06:06+08:00[Asia/Shanghai]
修改application.yml如下,就表示只有这个时间段内 可以进行路由,修改完之后重启项重新启动网关服务,访问http://localhost:8080/discoveryClient,会自动路由到 http://localhost:2001/discoveryClient
server: port: 8080 spring: cloud: gateway: routes: - id: neo_route uri: http://localhost:2001/ predicates: - Path=/discoveryClient - Between=2020-12-01T06:06:06+08:00[Asia/Shanghai], 2020-12-16T06:06:06+08:00[Asia/Shanghai]
2.通过Cookie匹配(Cookie)
Cookie Route Predicate 可以接收两个参数,一个是 Cookie name ,一个是正则表达式,路由规则会通过获取对应的 Cookie name 值和正则表达式去匹配,如果匹配上就会执行路由,如果没有匹配上则不执行。
server: port: 8080 spring: cloud: gateway: routes: - id: neo_route uri: http://localhost:2001/ predicates: - Path=/discoveryClient - Cookie=name, mtest
使用curl命令测试,可以看到带cookie的请求可以正确路由,正常获取到页面返回值,不带cookie的请求会404
C:\Users\mm>curl http://localhost:8080/discoveryClient --cookie "ityouknow=kee.e" Services: [] C:\Users\mm>curl http://localhost:8080/discoveryClient {"timestamp":"2020-12-09T03:48:44.034+00:00","path":"/discoveryClient","status":404,"error":"Not Found","message":null,"requestId":"80c9666b-1"}
3.通过 Header 属性匹配(Header)
Header Route Predicate也是接收 2 个参数,一个 header 中属性名称和一个正则表达式,这个属性值和正则表达式匹配则执行
server: port: 8080 spring: cloud: gateway: routes: - id: neo_route uri: http://localhost:2001/ predicates: - Path=/discoveryClient - Header=X-Request-Id, \d+
使用curl命令测试,可以看到 Header 属性值和正则表达式匹配的请求可以正确路由,否则会404
C:\Users\mm>curl http://localhost:8080/discoveryClient -H "X-Request-Id:666666" Services: [] C:\Users\mm>curl http://localhost:8080/discoveryClient -H "X-Request-Id:IO" {"timestamp":"2020-12-09T07:10:48.753+00:00","path":"/discoveryClient","status":404,"error":"Not Found","message":null,"requestId":"07aaa6b2-2"}
4.通过Host匹配(Host)
Host Route Predicate 接收一组参数,一组匹配的域名列表,这个模板是一个 ant 分隔的模板,用.
号作为分隔符。它通过参数中的主机地址作为匹配规则
server: port: 8080 spring: cloud: gateway: routes: - id: neo_route uri: http://localhost:2001/ predicates: - Path=/discoveryClient - Host=**.baidu.com
使用curl命令测试,可以看到 去掉 host 参数或者host参数值和规则不匹配 会报 404 错误
C:\Users\mm>curl http://localhost:8080/discoveryClient -H "Host: cn.baidu.com" Services: [] C:\Users\mm>curl http://localhost:8080/discoveryClient -H "Host: www.baidu.com" Services: [] C:\Users\mm>curl http://localhost:8080/discoveryClient -H "Host: www.baid.com" {"timestamp":"2020-12-09T08:08:35.150+00:00","path":"/discoveryClient","status":404,"error":"Not Found","message":null,"requestId":"3e93a018-4"} C:\Users\mm>curl http://localhost:8080/discoveryClient {"timestamp":"2020-12-09T08:08:40.223+00:00","path":"/discoveryClient","status":404,"error":"Not Found","message":null,"requestId":"e8d97b0c-5"}
5.通过请求方式匹配(Method)
可以通过是 POST、GET、PUT、DELETE 等不同的请求方式来进行路由
server: port: 8080 spring: cloud: gateway: routes: - id: neo_route uri: http://localhost:2001/ predicates: - Path=/discoveryClient - Method=GET
curl 分别测试GET , POST 方法,看效果如下。 curl默认是GET方法
C:\Users\mm>curl http://localhost:8080/discoveryClient Services: [] C:\Users\mm>curl -X POST http://localhost:8080/discoveryClient {"timestamp":"2020-12-09T08:13:14.466+00:00","path":"/discoveryClient","status":404,"error":"Not Found","message":null,"requestId":"3cea7707-2"}
6.通过请求路径匹配(Path)
Path Route Predicate 接收一个匹配路径的参数来判断是否走路由,以上的例子都用了Path匹配
7.通过请求参数匹配(QueryParam)
7.1 Query Route Predicate 支持传入两个参数,一个是属性名一个为属性值,属性值可以是正则表达式。
server: port: 8080 spring: cloud: gateway: routes: - id: neo_route uri: http://localhost:2001/ predicates: - Path=/discoveryClient - Query=smile
重启网关服务,访问http://localhost:8080/discoveryClient?smile=x, 可以正确路由到 http://localhost:2001/discoveryClient;访问http://localhost:8080/discoveryClient?smile=x&id=2, 可以正确路由到 http://localhost:2001/discoveryClient;也就是说只要请求中包含 smile 属性的参数即可匹配路由。
7.2 将 Query 的值以键值对的方式进行配置,这样在请求过来时会对属性值和正则进行匹配,匹配上才会走路由
server: port: 8080 spring: cloud: gateway: routes: - id: neo_route uri: http://localhost:2001/ predicates: - Path=/discoveryClient - Query=keep, pu.
重启网关服务,访问 http://localhost:8080/discoveryClient?keep=pu2,可以正确路由到 http://localhost:2001/discoveryClient;访问 http://localhost:8080/discoveryClient?keep=pu23 ,返回404。也就是说:只有当请求中包含 keep 属性并且参数值是以 pu 开头的长度为三位的字符串才会进行匹配和路由
7.3 匹配多个请求参数
server: port: 8080 spring: cloud: gateway: routes: - id: neo_route uri: http://localhost:2001/ predicates: - Path=/discoveryClient - Query=smile - Query=keep, pu.
重启网关服务,访问 http://localhost:8080/discoveryClient?smile=4&keep=pu8,可以正确路由到 http://localhost:2001/discoveryClient
8.通过请求 ip 地址进行匹配(RemoteAddr)
Predicate 也支持通过设置某个 ip 区间号段的请求才会路由,RemoteAddr Route Predicate 接受 cidr 符号(IPv4 或 IPv6 )字符串的列表(最小大小为1),例如 192.168.0.1/16 (其中 192.168.0.1 是 IP 地址,16 是子网掩码)
如果请求的远程地址是 192.168.1.10,则此路由将匹配。
server: port: 8080 spring: cloud: gateway: routes: - id: neo_route uri: http://localhost:2001/ predicates: - Path=/discoveryClient - RemoteAddr=192.168.1.1/24
可以将此地址设置为本机的 ip 地址进行测试
C:\Users\mm>curl http://localhost:8080/discoveryClient
9.组合Predicate
其实以上例子都用了- Path 和 其它Predicate的组合使用。当各种 Predicates 同时存在于同一个路由时,请求必须同时满足所有的条件才被这个路由匹配。
server: port: 8080 spring: cloud: gateway: routes: - id: neo_route uri: http://localhost:2001/ predicates: - Path=/discoveryClient - Before=2020-12-01T06:06:06+08:00[Asia/Shanghai] - Cookie=name, mtest - Query=smile
10.一个请求满足多个路由的谓词条件时,请求只会被首个成功匹配的路由转发