SpringCloud-网关 gateway

网关服务核心是将进入的请求正确合理的路由到下层具体的服务进行业务处理,从它的功能来看,网关服务的核心就是路由信息的构建。

Spring Cloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Netflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全、监控、埋点和限流等。

下面是官方提供的一个工作原理图:

客户端发送请求到 Spring Cloud Gateway,Gateway Handler Mapping 确定请求与路由匹配,则会将请求交给Gateway Web Handler 处理。在代理前后可以执行多个过滤器。最后代理到具体的服务。

几个概念

  • Route:Gateway 中的基本元素,它有自己的 ID、URI 、 Predicate 集合和 Filter 集合
  • Predicate:判断请求的 Url 是否匹配当前的 Route
  • Filter :匹配通过之后对请求和响应的处理及修饰

Spring-Cloud-Gateway 构建路由的数据流向:

RouteDefinition 模型是对 Route 模型中 route 的定义以及描述,Spring-Cloud-Gateway 最终会通过RouteDefinition 来构建起 Route 实例信息。其中 RouteDefinition 代码包含两个数组分别是PredicateDefinition,FilterDefinition。

内置的 Predicate

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

1
2
3
4
5
6
7
8
9
10
11
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>

配置文件

配置文件部分,除了常规的端口,应用名之外;关于spring cloud 的路由规则也可以通过配置文件进行配置,下面先以最简单的 path的方式来演示,最终达到的目标是,当输入:http://localhost:8866/gateway 时,请求信息将会被路由到 http://localhost:8086/hello(这个是一个eureka client,对外提供rest服务,工程详见glmapper-eureka-provider)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 ,输出的结果如下:

1
Hello Glmapper! Now Port is 8086 And hostname is HelloGlmapperService

这里输出的实际上是 http://localhost:8086/hello 提供的资源,说明我们的路由规则已经生效。

内置 Predicate 规则配置

上面已经罗列了所有的 spring cloud gateway 一些内置的 Predicate ,下面将来使用这些规则来演示下。

时间匹配

Predicate 支持设置一个时间,在请求进行转发的时候,可以通过判断在这个时间之前或者之后进行转发。在上面的列表中可以看出,基于时间的匹配支持某时间节点之前、之后,还支持介于两个时间之间的某个时间段内的匹配。基于某个时间段内的匹配规则常见的场景是限时抢购。

  • After Route Predicate
1
2
3
4
5
6
7
8
9
10
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。

  • Before Route Predicate
1
2
3
4
5
6
7
8
9
10
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 刚好相反,在某个时间之前的请求的请求都进行转发。

  • Between Route Predicate
1
2
3
4
5
6
7
8
9
10
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 ,其他的请求将不会被路由。

  • Cookie Route Predicate
1
2
3
4
5
6
7
8
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

  • Header Route Predicate
1
2
3
4
5
6
7
8
9
10
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。

域名匹配

1
2
3
4
5
6
7
8
9
10
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。那么具体配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 命令来执行以下:

参考

作者

卫恒

发布于

2018-12-31

更新于

2022-04-23

许可协议

评论