Spring Cloud Gateway的使用



一、需求

记录​​Spring Cloud Gateway​​的一些用法,不对其原理进行过多的探究。

二、基本组成

1、简介

​Spring Cloud Gateway​​​ 是 基于​​Spring boot 5​​​、​​Spring Boot 2.0​​​和​​Project Reactor​​ 等技术开发的网关。它旨在为微服务提供一个简单有效的方式来管理api路由。

Spring Cloud Gateway 是基于 Netty 运行的,不能运行在传统的Servlet容器中作为War包运行。

2、核型概念

1、Route 路由

​Route​​​是网关的基本组成单元,它是有一个​​ID​​​,一个目标​​URI​​​和一组​​predicates​​​和一组​​filters​​组成,如果一组断言结果为真,则匹配路由,目标URI会被访问。
注意:
1、多个 ​​​Predicate​​​ 之间是 逻辑​​and​​​ 的关系。
2、多个​​​Predicate​​是从定义的顺序从上到下依次执行,也可以指定 order 属性的值。

2、Predicate 谓语、断言

​Predicate​​​ 是Java 8 Function interface。输入类型是Spring Framework ​​ServerWebExchange​​​。可以用来匹配​​HTTP​​​请求中的任何内容,例如​​headers​​​ 或者 ​​parameters​​。

3、Filter 过滤器

​Filter​​​是​​GatewayFilter​​​的实例。通过​​Filter​​​我们可以在请求发送或返回下游服务时 修改 ​​请求​​​和​​响应​​。

3、工作原理

Spring Cloud Gateway Route Predicate Factory 的使用_网关 Predicate
​​​上图来自 Spring 官网。​

三、网关 Predicate配置方式

1、快捷配置方式(配置文件)

快捷方式是由过滤器是的​​名称​​​识别,后面紧跟​​=​​​,在跟以逗号(​​,​​)分隔的参数值。

spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- Cookie=mycookie,mycookievalue

上一个示例使用两个参数定义了​​Cookie​​​ Route Predicate Factory,这两个参数是cookie名称,​​mycookie​​​和与​​mycookievalue​​匹配的值

2、完全展开的参数(配置文件)

​name​​​:指定谓词工厂的名字
​​​args​​:指定对应谓词工厂中的参数对应的值。

spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- name: Cookie
args:
name: mycookie
regexp: mycookievalue

这种方式配置和上面的​​快捷方式​​配置的是一个意思

3、上方2种方式配置和代码对应关系

Spring Cloud Gateway Route Predicate Factory 的使用_spring_02

4、uri 值的方式

1、以http开头

当匹配到这个路由后,会跳转到这个地址。

2、以 lb 开头

eg:
     ​​​uri​​​: lb://service-name
解释:
​​​lb​​​:表示负载均衡的意思
​​​service-name​​:值的是调用服务在注册中心注册的服务名。

四、Route Predicate Factories

​Spring Cloud Gateway​​​内置了特别多的路由谓词工厂,用来匹配​​http​​​请求。当多个一起使用时,是​​and​​的关系,即需要所有的谓词工厂都匹配,才匹配这个路由。

1、After

1、描述:

当前请求在指定时间​​之后​​才匹配

2、存在参数:

    ​​datetime​​​ 数据类型是 ​​ZonedDateTime​​​,带有​​时区​

3、配置实例

spring:
cloud:
gateway:
routes:
- id: product-provider # 名字唯一即可
uri: lb://product-provider
predicates:
- After=2020-11-01T11:05:08.020+08:00[Asia/Shanghai]

2、Before

1、描述:

当前请求在指定时间​​之前​​才匹配

2、存在参数:

    ​​datetime​​​ 数据类型是 ​​ZonedDateTime​​​,带有​​时区​

3、配置实例

spring:
cloud:
gateway:
routes:
- id: product-provider # 名字唯一即可
uri: lb://product-provider
predicates:
- Before=2020-11-01T11:05:08.020+08:00[Asia/Shanghai]

3、Between

1、描述:

当前请求在指定时间​​中间​​才匹配

2、存在参数:

    ​​datetime1​​​ 数据类型是 ​​ZonedDateTime​​​,带有​​时区​​​     ​​datetime2​​ 数据类型是 ​​ZonedDateTime​​,带有​​时区​​      并且 datetime1 必须​​<​​ datetime2

3、配置实例

spring:
cloud:
gateway:
routes:
- id: product-provider # 名字唯一即可
uri: lb://product-provider
predicates:
- Between=2020-11-01T11:08:08.020+08:00[Asia/Shanghai],2020-11-01T11:15:08.020+08:00[Asia/Shanghai]

4、Cookie

1、描述:

当前请求中的cookie值匹配配置的cookie参数值时生效

2、存在参数:

    ​​name​​​ 请求​​cookie​​​中的​​参数​​​的名字
    ​​​regexp​​​ 请求​​cookie​​​中的​​参数​​​的值,配置的值是​​Java​​中的正则表达式形式。

3、配置实例

spring:
cloud:
gateway:
routes:
- id: product-provider # 名字唯一即可
uri: lb://product-provider
predicates:
- Cookie=token,tokenvalue\d+

Spring Cloud Gateway Route Predicate Factory 的使用_Route Predicate_03

4、解释

  • Cookie=token,tokenvalue\d+
    表示 请求中必须存在一个 cookie 的key 是 token 的,且值必须是​​​tokenvalue 后面加上一个数子​​才匹配的上,否则匹配不上。

5、Header

1、描述:

当前请求中的header值匹配配置的header参数值时生效

2、存在参数:

    ​​name​​​ header key的名字
    ​​​regexp​​​ header key对应的值,配置的​​值​​​是​​Java​​​中的​​正则表达式形式​​。

3、配置实例

spring:
cloud:
gateway:
routes:
- id: product-provider # 名字唯一即可
uri: lb://product-provider
predicates:
- Header=X-Token-Id,\d+

4、解释

  • Header=X-Token-Id,\d+
    表示请求头中必须存在R-Token-Id且它的值必须是数字

6、Host

1、描述:

匹配请求头中的​​Host​​的值

2、存在参数:

    ​​patterns​​​ 配置一系列的以​​.​​​作为分隔的​​ant​​​风格host地址,多个中间以​​,​​​隔开。​​Host​​​中配置的值还支持​​URI template variables​​​,比如​​{xxx}.baidu.com​

3、配置实例

spring:
cloud:
gateway:
routes:
- id: product-provider # 名字唯一即可
uri: lb://product-provider
predicates:
- Host=**.gateway.com,{study}.baidu.com

Spring Cloud Gateway Route Predicate Factory 的使用_Route Predicate_04

4、解释

  • Host=**.gateway.com,{study}.baidu.com
    1、​​​**.gateway.com​​​:表示请求中的​​Host​​​的值需要配置这种​​ant​​​风格
    2、​​​{study}.baidu.com​​​:​​study​​​这个模版变量可以在​​GatewayFilter​​​中获取到,通过​​ServerWebExchange.getAttributes().get(ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE)​​获取

7、Method

1、描述:

匹配请求头中的​​Method​​的值

2、存在参数:

    ​​methods​​​ 需要匹配的方法,比如​​GET​​​、​​POST​​等

3、配置实例

spring:
cloud:
gateway:
routes:
- id: product-provider # 名字唯一即可
uri: lb://product-provider
predicates:
- Method=GET,POST,PUT # 只有get,post,put请求才能匹配上方这个路由

8、Path

1、描述:

匹配请求路径。

2、存在参数:

    ​​patterns​​​ 需要匹配的路径eg: /product/{id},/product/**
    ​​​matchOptionalTrailingSeparator​​ 一个可选的参数

3、配置实例

spring:
cloud:
gateway:
routes:
- id: product-provider # 名字唯一即可
uri: lb://product-provider
predicates:
- Path=/product/findOne/{productId},/product/**

4、解释

​/product/findOne/{productId}​​​ 支持uri模版变量,​​productId​​​可以在​​GatewayFilter​​中获取,获取方式.

Map<String, String> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);
String segment = uriVariables.get("productId");

9、Query

1、描述:

匹配请求参数。

2、存在参数:

    ​​param​​​ 请求参数的key值
    ​​​regexp​​​ 请求参数的值,配置的值是​​Java​​​中的​​正则表达式形式。​

3、配置实例

spring:
cloud:
gateway:
routes:
- id: product-provider # 名字唯一即可
uri: lb://product-provider
predicates:
#- Query=pwd
- Query=username,\d+

4、解释

1、​​Query=pwd​​​ 表示请求中必须存在 ​​pwd​​​这个请求参数
2、​​​Query=username,\d+​​​ 表示请求中必须存在​​username​​​这个参数,且它的值必须是​​数字​

10、RemoteAddr

1、描述:

匹配请求的ip地址,支持ipv4和ipv6。

2、存在参数:

    ​​sources​​ 地址列表eg:127.0.0.1/16 后方的/16是子网掩码

3、配置实例

spring:
cloud:
gateway:
routes:
- id: product-provider # 名字唯一即可
uri: lb://product-provider
predicates:
- RemoteAddr=127.0.0.1/16

4、注意

如果我们的​​Spring Cloud Gateway​​​是位于代理后面,那么获取到​​远程地址可能不正确​​​,此时我们可以自己编写一个​​RemoteAddressResolver​​来解决。

参考链接:​​https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/#the-weight-route-predicate-factory​

11、Weight

1、描述:

根据​​权重​​​来分发请求,权重是根据​​group​​来计算的。

2、存在参数:

    ​​group​​​ 组,权重根据组来计算
    ​​​weight​​​ 权重值,是一个 ​​Int​​ 的值

3、配置实例

spring:
cloud:
gateway:
routes:
- id: product-provider
uri: https://weighthigh.org
predicates:
- Weight=group1,8
- id: user-consumer
uri: https://weightlow.org
predicates:
- Weight=group1,2

4、解释

上方配置会导致​​80%​​​的请求落到 ​​https://weighthigh.org​​​,有​​20%​​​的请求落到​​https://weightlow.org​

五、自己编写一个 route predicate factory

1、编写步骤

1、编写一个类,实现​​RoutePredicateFactory​​​接口,或继承​​AbstractRoutePredicateFactory​​​     > 1、AbstractRoutePredicateFactory 中的 ​​C​​ 表示 配置文件类
    > 2、重写​​shortcutFieldOrder​​此方法,表示的配置文件中参数的位置
    > 3、重写​​apply(C c)​​方法,表示的是具体的业务逻辑
2、我们自己编写的类必须要以​​RoutePredicateFactory​​结尾,否则比较麻烦,参考
​org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#initFactories​​ 这个方法。

2、要实现的功能

判断请求参数中是否存在 ​​token​​ 配置的值。

3、Java代码

@Slf4j
@Component
public class TokenRoutePredicateFactory extends AbstractRoutePredicateFactory<TokenRoutePredicateFactory.Config> {

public TokenRoutePredicateFactory() {
super(Config.class);
}

@Override
public List<String> shortcutFieldOrder() {
return Lists.newArrayList("token");
}

@Override
public Predicate<ServerWebExchange> apply(Config config) {
return exchange -> {
log.info("判断请求头中是否存在token这个参数");
String token = exchange.getRequest().getQueryParams().getFirst(config.getToken());
return StringUtils.isNotBlank(token);
};
}

@Data
public static class Config {
private String token;
}
}

4、配置文件

spring:
cloud:
gateway:
routes:
- id: product-provider
uri: lb://product-provider
predicates:
- Token=token

5、解释

Spring Cloud Gateway Route Predicate Factory 的使用_Cloud Alibaba_05

六、完整代码

​https://gitee.com/huan1993/spring-cloud-alibaba-parent/tree/master/gateway​

七、参考链接

​https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/​