本篇主要介绍下 Spring Cloud Gateway 的匹配器 Predicate 的使用。
对于一个请求的路由,Spring Cloud Gateway 的处理过程是:
- 遍历所有的路由
- 针对每个路由,遍历其 Predicate 匹配器进行匹配,只有该路由的匹配器全部匹配才算匹配成功
- 如果匹配失败,则跳到下一个路由;如果匹配成功,则忽略其余路由。
Spring Cloud Gateway 内置的匹配器提供了下面几种形式的匹配:
- 基于权重的匹配
- 基于时间的匹配,包括某个时间之前、之后,以及某个时间段之间
- 基于请求的匹配,包括 Header、Cookie、Path、Method、Query Params、RemoteAddr、Host 几种方式。
下面对每种匹配方式进行简单的介绍和配置演示。
一. 基于权重的匹配
基于权重的匹配需要指明两个参数:
- group:表示路由组。将多个需要按权重进行调度的路由声明为同一个 group
- weight:设置权重,只能是整数
Spring Cloud Gateway 会基于一个组内权重的比例进行路由。
配置示例
spring:
cloud:
gateway:
routes:
# 基于权重匹配
- id: student-route
uri: http://localhost:8082
predicates:
- Path=/student/**
- Weight=student-service-group, 8
- id: student-canary-route
uri: http://localhost:8083
predicates:
- Path=/student/**
- Weight=student-service-group, 2
我针对学生服务部署了金丝雀 canary 版本,设置的权重为 2:8,表示将 20% 的请求路由到金丝雀版本中。
二. 基于时间的匹配
Spring Cloud Gateway 可以根据时间之前 Before、之后 After、之间 Between 三种方式进行路由匹配。配置的格式是 Java 的 ZonedDateTime 类型带时区信息的时间格式。
配置示例
- Before、After 匹配
spring:
cloud:
gateway:
routes:
- id: student-route
uri: http://localhost:8082
predicates:
- After=2020-04-20T17:42:47.789+08:00[Asia/Shanghai]
- id: student-canary-route
uri: http://localhost:8083
predicates:
- Before=2020-04-20T17:42:47.789+08:00[Asia/Shanghai]
这里表示对于学生服务,在东八区时间 2020-04-20 17:42:47 前将请求路由至金丝雀版本,在该时间之后路由到线上版本。
- Between 匹配
Between 需要设置两个时间,表示在该段时间之内将请求路由到对应的服务,示例如下:
spring:
cloud:
gateway:
routes:
- id: student-canary-route
uri: http://localhost:8083
predicates:
- Betwen=2020-04-18T17:42:47.789+08:00[Asia/Shanghai],2020-04-20T17:42:47.789+08:00[Asia/Shanghai]
一般来说时间类型的匹配还需要结合其他的匹配条件进行更加精确的匹配,不然只靠时间的话容易将不相关的服务的请求路由到错误的目的 URI 去。
三. 基于请求的匹配
1. 基于请求路径 Path 的匹配
最基本的就是按照路径进行请求的路由了。
配置示例
- application.yml 文件配置
spring:
cloud:
gateway:
routes:
- id: teacher-route
uri: http://localhost:8081
predicates:
- Path=/teacher/**
- id: student-route
uri: http://localhost:8082
predicates:
- Path=/student/**
- Java 代码配置
@Configuration
public class RouteConfig {
@Bean
public RouteLocator gatewayRoutes(RouteLocatorBuilder builder) {
return builder.routes()
.route(r -> r.path("/teacher/**")
.uri("http://localhost:8081/")
.id("teacher-route"))
.route(r -> r.path("/student/**")
.uri("http://localhost:8082/")
.id("student-route"))
.build();
}
}
上面的配置表示将请求路径已 /teacher
开头的路由至教师服务,将请求路径以 /student
开头的请求路由至学生服务。
这里因为配置的 uri 是 IP:Port
的格式所以语义不是很直观,如果配合服务注册功能的这里的 uri 可以直接填写服务名,读起来就非常直观了,关于 Spring Cloud Gateway 结合服务注册功能使用将会在后面的文章中讲解。
2. 基于请求头 Header 的匹配
根据 HTTP 请求头 Header 的匹配需要设置两个字段:
- name: 要匹配的 Header 字段名
- regexp: 用来匹配的正则表达式(Java regular expression)
配置示例
spring:
cloud:
gateway:
routes:
- id: student-route
uri: http://localhost:8082
predicates:
- Path=/student/**
# 基于值的匹配,当 Header 中有 Canary 字段,值为 false 时,路由到生产环境的学生服务
- Header=Canary, false
- id: student-canary-route-01
uri: http://localhost:8083
predicates:
- Path=/student/**
# 基于值的匹配,当 Header 中有 Canary 字段,值为 true 时,路由到金丝雀版本的学生服务
- Header=Canary, true
- id: student-canary-route-02
uri: http://localhost:8083
predicates:
- Path=/student/**
# 基于正则的匹配,当 Header 中有 Request-ID 字段,值为一个或多个数字时,路由到金丝雀版本的学生服务
- Header=Request-ID, \d+
3. 基于 Cookie 的匹配
和 Header 一样,根据 Cookie 进行匹配时有需要设置 name
和 regexp
两个字段,表示要匹配的 Cookie 字段和值。
配置示例
spring:
cloud:
gateway:
routes:
- id: student-route
uri: http://localhost:8082
predicates:
- Path=/student/**
# 基于值的匹配,当 Cookie 中有 Canary 字段,值为 false 时,路由到生产环境的学生服务
- Cookie=Canary, false
- id: student-canary-route-01
uri: http://localhost:8083
predicates:
- Path=/student/**
# 基于值的匹配,当 Cookie 中有 Canary 字段,值为 true 时,路由到金丝雀版本的学生服务
- Cookie=Canary, true
- id: student-canary-route-02
uri: http://localhost:8083
predicates:
- Path=/student/**
# 基于正则的匹配,当 Cookie 中有 STUDENT-ID 字段,值为一个或多个数字时,路由到金丝雀版本的学生服务
- Cookie=STUDENT-ID, \d+
4. 基于请求方法 Method 的匹配
顾名思义,我们可以通过HTTP 的 Get、Post、Put 等方法进行路由匹配,这样可以将某一种类型的请求路由到特定的服务上。
配置示例
spring:
cloud:
gateway:
routes:
- id: student-route
uri: http://localhost:8082
predicates:
- Path=/student/**
# 将 Get 类型的请求全部路由到生产服务
- Method=GET
- id: student-canary-route-01
uri: http://localhost:8083
predicates:
- Path=/student/**
# 将 POST、PUT 类型的请求路由到金丝雀版本的服务商
- Method=POST, PUT
5. 基于 Host 的匹配
如果 HTTP 的请求头中有 Host 字段,那么也可以基于该字段的值进行匹配,针对 Host 值的匹配不是通过正则表达式实现的,而是根据 Ant-style pattern 进行匹配。
配置示例
spring:
cloud:
gateway:
routes:
- id: student-route
uri: http://localhost:8082
predicates:
- Host=**.student.com, **.grade.student.com
- id: teacher-route
uri: http://localhost:8081
predicates:
- Host=**.teacher.com
基于上面的配置,当请求的 Host 为 www.teacher.com
时 Gateway 会将请求路由到教师服务,如果是 www.student.com 、canary.student.com
,则会路由到学生服务。
6. 基于请求参数 Query Params 的匹配
针对参数的匹配,既可以只指定一个 name
字段名,表示只有对应名称的参数就匹配成功,也可以基于正则表达式指定一个匹配值,如果包含参数并且值也匹配才算匹配成功。
配置示例
spring:
cloud:
gateway:
routes:
- id: student-route
uri: http://localhost:8082
predicates:
- Query=Tom
- id: student-canary-route
uri: http://localhost:8083
predicates:
- Query=Marry, abc.+
在上面的配置中,如果对学生服务的请求参数中带有 Tom 参数,则会将请求路由到 8082 端口,如果带有 Marry 参数并且值为 abc+任意字符那么会将请求路由到 8083 端口。
7. 基于请求IP RemoteAddr 的匹配
这里表示通过 Remote Address 进行匹配,这里定义一个列表,只要请求的 Remote Address 和列表中的任意一个 IP 地址匹配就表示匹配成功。
示例配置
spring:
cloud:
gateway:
routes:
- id: student-service
uri: http://localhost:8082
predicates:
- RemoteAddr=192.168.1.1/24
上面配置表示如果请求来自于 192.168.1.1
,则将请求转发到学生服务上。
以上就是 Spring Cloud Gateway 的 Predicatee 匹配器的一些用法,下一篇介绍 Filter 过滤器的用法和示例。