1.Spring Cloud Gateway 是什么?
它是一个基于 Spring Framework 的开源 API 网关服务。它旨在为微服务架构中的应用程序提供统一的路由和过滤器机制,以完成恳求的转发、降级、熔断、限流等功能。换言之,它便是网关(Gateway),充当了客户端和内部微服务之间的中介。
Spring Cloud Gateway 组成:
- 路由:界说恳求应该被转发到哪个方针地址。
- 断语:用于匹配恳求的条件,依据断语条件匹配到相应的路由。
- 过滤器:用于在恳求路由前或路由后进行一些处理、操作,比如增加头部信息、修改恳求体等。
在微服务中,内部之间的通讯是用 OpenFeign + LoadBalancer
完成的。那前端向后端发送恳求的时候,我的拜访途径是什么呢?该向哪一个服务发送呢?该用什么来统筹外部与内部之间的通信呢?其实便是运用 Spring Cloud Gateway
来提供统一拜访地址或者界说一些规矩来处理恳求。
2. Gateway 的路由功能
2.1 准备工作
创建两个模块,来完成 Gateway 的路由功能。gateway-service
为网关,user-service
为一个服务。
在 gateway-service
的 pom. xml
中,增加依靠:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
在 user-service
的 pom. xml
中,增加依靠:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
注意,
Spring Cloud Gateway
不能配合Spring Web(Spring MVC)
一起运用。也便是在同一个pom
文件中不能同时存在。
在 user-service
模块中随便写一个接口,然后装备 gateway
来完成路由的转发。
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/getname")
public String getName(){
return "Name: 小明";
}
}
2.2 装备路由
现在装备 gateway
:
spring:
cloud:
gateway:
routes:
- id: userservice
uri: http://localhost:9090
predicates:
- Path=/user/**
server:
port: 8080
下面是 properties
格式的:
server.port=8080
spring.cloud.gateway.routes[0].id=userservice
spring.cloud.gateway.routes[0].uri=http://localhost:9090
spring.cloud.gateway.routes[0].predicates[0]=Path=/user/**
- id:
userservice
,表明这个路由的仅有标识,不能重复,没有其他效果。 - uri:
http://localhost:9090
,表明这个路由的方针地址。 - predicates: 表明这个路由的断语列表,它有很多种类型,更多的类型后文介绍。
- Path=/user/,表明这个断语的类型是
Path
,用于匹配恳求途径,这里表明匹配以/user/
开头的任意途径。
这个路由规矩的意思是,假如恳求途径以/user/
开头,就转发到http://localhost:9090
这个地址。
user-service
装备:
server:
port: 9090
发动程序后:
能够看到,localhost: 8080/user/getname
能拜访到 9090
端口的 user-service
服务。这就完成了 localhost: 8080/user/getname
到 localhost: 9090/user/getname
途径的转化。
假如一个模块中有多个路由需要转化,就能够运用英文逗号离隔:
spring:
cloud:
gateway:
routes:
- id: userservice
uri: http://localhost:9090
predicates:
- Path=/user/**,/us/**,……
server:
port: 8080
2.3 多个模块
再增加一个模块 goods-service
@RestController
@RequestMapping("/goods")
public class GoodsController {
@RequestMapping("/getname")
public String getGoodsName(){
return "红旗轿车";
}
}
server:
port: 7070
因为新增加一个模块,那么就需要增加一个路由设置。gateway
的装备文件:
spring:
cloud:
gateway:
routes:
- id: userservice
uri: http://localhost:9090
predicates:
- Path=/user/**
- id: goodsservice
uri: http://localhost:7070
predicates:
- Path=/goods/**
server:
port: 8080
发动程序,并拜访 localhost: 8080/goods/getname
能够看到 gateway
将不同的端口的服务整合到一起,这便是它的效果之一。
2.4 断语类型
Gateway 的断语类型有:
- After、Before、Between:依据恳求的时刻进行路由,能够指定一个时刻点或一个时刻区间。
- Cookie:依据恳求中的cookie进行路由,能够指定cookie的称号和值的正则表达式。
- Header:依据恳求头进行路由,能够指定恳求头的称号和值的正则表达式。
- Host:依据恳求的主机名进行路由,能够指定一个或多个主机名,也能够运用通配符。
- Method:依据恳求的方法进行路由,能够指定一个或多个HTTP方法,如GET、POST等。
- Query:依据恳求的查询参数进行路由,能够指定参数的称号和值的正则表达式。
- Path:匹配恳求途径。
- Query:匹配恳求参数。
- RemoteAdder:匹配恳求的 IP 地址。
- Weight:依据权重来分发恳求。
- XForwardedRemoteAddr:依据 HTTP 头 X-Forwarded-For 进行恳求过滤。
(更详细的看官方文档: Spring Cloud Gateway)
2.4.1 依据时刻匹配
下面表明在 2024-01-28 T17:42:47.789
这个时刻之后才会匹配路由,+08:00[Asia/Shanghai]
为时区。
spring:
cloud:
gateway:
routes:
- id: userservice
uri: http://localhost:9090
predicates:
- Path=/user/**
- After=2024-01-28T17:42:47.789+08:00[Asia/Shanghai]
在 2017-01-20 T17:42:47.789~2017-01-21 T17:42:47.789
之间的恳求能够被匹配。
spring:
cloud:
gateway:
routes:
- id: userservice
uri: http://localhost:9090
predicates:
- Path=/user/**
- Between=2017-01-20T17:42:47.789+08:00[Asia/Shanghai], 2017-01-21T17:42:47.789+08:00[Asia/Shanghai]
2.4.2 Header 断语
spring:
cloud:
gateway:
routes:
- id: userservice
uri: http://localhost:9090
predicates:
- Path=/user/**
- id: goodsservice
uri: http://localhost:7070
predicates:
- Path=/goods/**
- Header=X-Request-Id, d+
这个路由匹配条件是:假如恳求包含名为 X-Request-Id
的头,并且该头的值与正则表达式 d+
匹配(即,它的值为一个或多个数字),则路由匹配。
(正则表达式的规矩:正则表达式 – 教程 | 菜鸟教程 (runoob.com))
没有 X-Request-Id
时 404:
增加 X-Request-Id
时,能拜访:
2.4.3 Method 断语
spring:
cloud:
gateway:
routes:
- id: userservice
uri: http://localhost:9090
predicates:
- Path=/user/**
- id: goodsservice
uri: http://localhost:7070
predicates:
- Path=/goods/**
- Method=GET,POST
只能匹配 GET、POST
类型的恳求。
2.4.4 Weight 断语
spring:
cloud:
gateway:
routes:
- id: userservice1
uri: http://localhost:9090
predicates:
- Weight=group1,10
- id: userservice2
uri: http://localhost:7070
predicates:
- Weight=group1,90
假设 userservice1
与 userservice2
模块都有“/user/getname
”这个接口。上面的意思是:把大约 10%
的流量转发到 userservice1
,而将大约 90%
的流量转发到 userservice2
。要注意的是权重是按组核算的,上面的两个模块同归于 group1
,那么就将这一组按份额来分流。
(最后,Gateway
必定需要结合 Nacos
和 LoadBalancer
来运用,这样才能发挥它的最大效果,本篇只介绍了 Gateway 的断语,其它(如过滤器)后续再更新……)