微信公众号:glmapper工作室
掘金专栏:glmapper
微 博:疯狂的石头_henu
欢迎关注,一起学习分享技术
Spring Cloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Netflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全、监控、埋点和限流等。下面是官方提供的一个工作原理图:
客户端发送请求到 Spring Cloud Gateway,Gateway Handler Mapping 确定请求与路由匹配,则会将请求交给Gateway Web Handler 处理。在代理前后可以执行多个过滤器。最后代理到具体的服务。
Spring-Cloud-Gateway 构建路由的数据流向:
RouteDefinition 模型是对 Route 模型中 route 的定义以及描述,Spring-Cloud-Gateway 最终会通过RouteDefinition 来构建起 Route 实例信息。其中 RouteDefinition 代码包含两个数组分别是PredicateDefinition,FilterDefinition。
Spring Cloud Gateway 是通过 Spring WebFlux 的 HandlerMapping
做为底层支持来匹配到转发路由,Spring Cloud Gateway 内置了很多 Predicates 工厂,这些 Predicates 工厂通过不同的 HTTP 请求参数来匹配,多个 Predicates 工厂可以组合使用。下面是内置的Predicates:
组件 | 备注 |
---|---|
After Route Predicate Factory | 此谓词匹配当前日期时间之后发生的请求。 |
Before Route Predicate Factory | 此谓词匹配在当前日期时间之前发生的请求。 |
Between Route Predicate Factory | 此谓词匹配datetime1之后和datetime2之前发生的请求。 datetime2参数必须在datetime1之后。 |
Cookie Route Predicate Factory | Cookie Route Predicate Factory有两个参数,cookie名称和正则表达式。此谓词匹配具有给定名称且值与正则表达式匹配的cookie。 |
Header Route Predicate Factory | Header Route Predicate Factory有两个参数,标题名称和正则表达式。与具有给定名称且值与正则表达式匹配的标头匹配。 |
Host Route Predicate Factory | Host Route Predicate Factory采用一个参数:主机名模式。该模式是一种Ant样式模式“.”作为分隔符。此谓词匹配与模式匹配的Host标头。 |
Method Route Predicate Factory | Method Route Predicate Factory采用一个参数:要匹配的HTTP方法。 |
Path Route Predicate Factory | 匹配请求的path |
Query Route Predicate Factory | Query Route Predicate Factory有两个参数:一个必需的参数和一个可选的正则表达式。 |
RemoteAddr Route Predicate Factory | RemoteAddr Route Predicate Factory采用CIDR符号(IPv4或IPv6)字符串的列表(最小值为1),例如, 192.168.0.1/16(其中192.168.0.1是IP地址,16是子网掩码)。 |
本篇将通过一个简单的 gateway 工程来演示如何使用上面的 Predicate 来实现路由。
这里新建一个 glmapper-cloud-gateway 工程,具体细节如下
首先在当前工程的pom文件中引入spring cloud gateway 的依赖:spring-cloud-starter-gateway
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-gatewayartifactId>
dependency>
dependencies>
配置文件部分,除了常规的端口,应用名之外;关于spring cloud 的路由规则也可以通过配置文件进行配置,下面先以最简单的 path的方式来演示,最终达到的目标是,当输入:http://localhost:8866/gateway 时,请求信息将会被路由到 http://localhost:8086/hello(这个是一个eureka client,对外提供rest服务,工程详见glmapper-eureka-provider)。
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/ #eureka server 的地址
server:
port: 8866
spring:
application:
name: glmapper-cloud-gateway #应用名
cloud:
gateway:
routes:
- id: glmapper
uri: http://localhost:8086/hello #目标地址
predicates:
- Path=/gateway #路由规则
这里直接启动这个工程,SpringCloud Gateway 不需要额外的注解来开启网关服务,所以这里省略启动类的代码。先后启动 glmapper-eureka-server 、glmapper-eureka-provider、glmapper-cloud-gateway。
在浏览器中输入:http://localhost:8866/gateway ,输出的结果如下:
Hello Glmapper! Now Port is 8086 And hostname is HelloGlmapperService
这里输出的实际上是 http://localhost:8086/hello 提供的资源,说明我们的路由规则已经生效。
上面已经罗列了所有的 spring cloud gateway 一些内置的 Predicate ,下面将来使用这些规则来演示下。
Predicate 支持设置一个时间,在请求进行转发的时候,可以通过判断在这个时间之前或者之后进行转发。在上面的列表中可以看出,基于时间的匹配支持某时间节点之前、之后,还支持介于两个时间之间的某个时间段内的匹配。基于某个时间段内的匹配规则常见的场景是限时抢购。
server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: glmapper #自定义的路由ID
uri: http://www.glmapper.com #目标服务地址
predicates:
- After=2019-01-10T00:00:00+08:00[Asia/Shanghai] #通过时间匹配 2019年1月10日
After Route Predicate 是指在这个时间之后的请求都转发到目标地址。请求时间在 2019年1月10日日00点00分00秒之后的所有请求都转发到地址 http://www.glmapper.com。+08:00是指时间和UTC时间相差八个小时,时间地区为 Asia/Shanghai。
server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: glmapper #自定义的路由ID
uri: http://www.glmapper.com #目标服务地址
predicates:
- Before=2019-01-10T00:00:00+08:00[Asia/Shanghai] #通过时间匹配 2019年1月10日
Before Route Predicate 与 After Route Predicate 刚好相反,在某个时间之前的请求的请求都进行转发。
server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: glmapper #自定义的路由ID
uri: http://www.glmapper.com #目标服务地址
predicates:
- Between=2019-01-10T00:00:00+08:00[Asia/Shanghai], 2019-01-10T06:00:00+08:00[Asia/Shanghai]
在2019年1月10 零点至6点之间的请求将会被路由到 http://www.glmapper.com ,其他的请求将不会被路由。
spring:
cloud:
gateway:
routes:
- id: glmapper
uri: http://localhost:8086/hello
predicates:
- Cookie=name,glmapper
这里,如果我的请求信息中存在 cookie name 为 glmapper,值匹配到 glmapper 的串,那么请求将会被路由。
PS:这里在配置的时候要注意下 routes 后面格式缩进,否则会抛出一些异常,如:
Property: spring.cloud.gateway.routes[0].uri Value: null Reason: 不能为null Property: spring.cloud.gateway.routes[0].predicates Value: [] Reason: 不能为空
当cookie的值不满足时,访问时404
spring:
application:
name: glmapper-cloud-gateway
cloud:
gateway:
routes:
- id: glmapper
uri: http://localhost:8086/hello
predicates:
- Header=X-Request-Id, \d+
上面这段配置用于配置 Header 中 X-Request-Id值数字的请求:
同样,如果是非数字的话将会返回 404。
spring:
application:
name: glmapper-cloud-gateway
cloud:
gateway:
routes:
- id: glmapper
uri: http://localhost:8086/hello
predicates:
- Host=**.glmapper.com
上面这段配置用于匹配 host 为 xxx.glmapper.com 域名的请求:
关于其他的内置 Predicate 均可在官方文档中有实例参考,这里就不一一罗列了。
最后我们来将上面的一些进行组合,假设我需要在 2019.1.10 0点至2019.1.10 6点之间,cookie中带有name=glmapper,header 的 X-Request-Id 为数字,域名是 xx.glmapper.com ,path为 /gateway ,请求方式为GET,参数名为queryParam
的请求路由到 http://localhost:8086/hello。那么具体配置如下
spring:
application:
name: glmapper-cloud-gateway
cloud:
gateway:
routes:
- id: glmapper
uri: http://localhost:8086/hello
predicates:
- Host=**.glmapper.com
- Path=/gateway
- Method=GET
- Header=X-Request-Id,\d+
- Query=queryParam
- Cookie=name,glmapper
- Between=2019-01-10T00:00:00+08:00[Asia/Shanghai], 2019-01-10T06:00:00+08:00[Asia/Shanghai]
还是通过curl 命令来执行以下: