携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第11天,点击查看活动详情
-
一、整合作用
在上篇文章主要介绍了GateWay的相关功能、以及一个简单通过GateWay来进行转发的功能,在application.yml中配置相关转发规则,但是可以发现在转发服务的时候,使用的是http的访问路径,在前面的文章中也有提到,如果微服务使用http进行服务访问,那后期的维护成本是非常高的,因此就需要通过整合Nacos来进行服务的处理。
二、集成Nacos
2-1、添加Nacos的依赖
<!-- nacos服务注册与发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
2-2、配置application.yml文件
首先配置了Nacos的连接地址,如果开启了鉴权,需要配置用户名密码;
其次配置路由的URI,通过设置lb://来设置使用Nacos的负载均衡策略,然后执行调用的服务名
2-3、重启GateWay服务、测试
如下可以看到GateWay服务和订单服务都已经注册到了Nacos中
访问测试:
2-4、application.yml的简写配置
上面在application.yml中的配置需要配置路由、断言以及过滤器,实际上还可以简写简略配置,如下:
通过设置locator.enabled:true,就可以让GateWay去自动识别Nacos中的服务
2-4-1、测试
如下,通过让GateWay去自动识别服务名,就可以自动去Nacos中找到服务对应的接口,进行访问,不需要再进行配置路由、断言、过滤器
一般情况下会选择使用路由、断言、过滤器的方式进行配置,因为代码配置的更加灵活,并且更加易于阅读。
三、路由断言工厂(Route Predicate Factories)配置
3-1、内置的断言工厂
作用: 当请求gateway的时候, 使用断言对请求进行匹配, 如果匹配成功就路由转发, 如果匹配失败就返回404
类型:内置,自定义
断言工厂可以去官网进行查看:docs.spring.io/spring-clou…
SpringCloud Gateway包括许多内置的断言工厂,所有这些断言都与HTTP请求的不同属性匹配。具体如下
3-1-1、基于Datetime类型的断言工厂
此类型的断言根据时间做判断,主要有三个:
AfterRoutePredicateFactory: 接收一个日期参数,判断请求日期是否晚于指定日期
BeforeRoutePredicateFactory: 接收一个日期参数,判断请求日期是否早于指定日期
BetweenRoutePredicateFactory: 接收两个日期参数,判断请求日期是否在指定时间段内
设置匹配时间必须是带区域的时间
获取时间可以通过:ZonedDateTime.now()来获取当前时间
3-1-1-1、基于before的断言工厂
通过以下配置,就可以设置只有在2022-07-20T17:42:47.789-07:00[Asia/Shanghai]之前的时间才能进行访问
spring:
cloud:
gateway:
routes:
- id: before_route
uri: https://example.org
predicates:
- Before=2022-07-20T17:42:47.789-07:00[Asia/Shanghai]
3-1-1-2、基于After的断言工厂
通过以下配置,就可以设置只有在2022-07-20T17:42:47.789-07:00[Asia/Shanghai]之后的时间才能进行访问
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- After=2022-07-20T17:42:47.789-07:00[Asia/Shanghai]
3-1-1-3、基于Between的断言工厂
通过以下配置,就可以设置只有在2022-07-20T17:42:47.789-07:00[Asia/Shanghai]和2022-09-20T17:42:47.789-07:00[Asia/Shanghai]之间的时间才能进行访问
spring:
cloud:
gateway:
routes:
- id: between_route
uri: https://example.org
predicates:
- Between=2022-07-20T17:42:47.789-07:00[Asia/Shanghai], 2022-09-20T17:42:47.789-07:00[Asia/Shanghai]
3-1-2、基于Cookie的断言工厂
通过以下配置,就可以设置只有当cookie中chocolate的值为ch.p的时候才能进行访问,另外值支持正则表达式
spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: https://example.org
predicates:
- Cookie=chocolate,ch.p
3-1-3、基于Header的断言工厂
通过以下配置,就可以设置请求头的断言工厂,需要请求投中有X-Request-Id,并且值为xxxxb时可以访问,另外值支持正则表达式
spring:
cloud:
gateway:
routes:
- id: header_route
uri: https://example.org
predicates:
- Header=X-Request-Id,xxxxb
3-1-4、基于Host的断言工厂
通过以下配置就可以设置Host的断言工厂,支持通配符以及多个Host,多个Host之间用“,”隔开
spring:
cloud:
gateway:
routes:
- id: host_route
uri: https://example.org
predicates:
- Host=**.somehost.org,**.anotherhost.org
3-1-5、基于Method请求方法的断言工厂
可以设置请求的Method,如下:
spring:
cloud:
gateway:
routes:
- id: method_route
uri: https://example.org
predicates:
- Method=GET,POST
3-1-6、基于Path请求路径的断言工厂
通过路径进行设置断言,路径中支持*号通配符,同时也支持占位符,比如请求路径为/user/123,那么就可以设置- Path=/user/{id}
spring:
cloud:
gateway:
routes:
- id: path_route
uri: https://example.org
predicates:
- Path=/red/{segment},/blue/{segment}
3-1-7、基于Query请求参数的断言工厂
通过设置请求Query来设置断言工厂,以下配置就是在Query参数中必须有green参数,参数支持正则表达式设置,如果要给参数设置值可以进行如下配置:
- Query=name,zhangsan|lisi
上面配置的含义为:Query中必须有name参数,值是zhangsan或者李四
spring:
cloud:
gateway:
routes:
- id: query_route
uri: https://example.org
predicates:
- Query=green
3-1-8、基于远程地址的断言工厂
其中192.168.1.1是 IP 地址和24子网掩码,可以可以直接配置ip地址
spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: https://example.org
predicates:
- RemoteAddr=192.168.1.1/24
3-1-9、基于路由权重的断言工厂
当前配置有两个路由规则,其中一个权重是8,另外一个是2,假设当10个请求进来的时候,就会有8个访问第一个,2个访问第二个;另外要配置权重的话使用Weight,值第一个为分组,第二个为权重值,这样下面两个都设置group1,就是这两个为一个分组。
spring:
cloud:
gateway:
routes:
- id: weight_high
uri: https://weighthigh.org
predicates:
- Weight=group1, 8
- id: weight_low
uri: https://weightlow.org
predicates:
- Weight=group1, 2
3-2、自定义断言工厂
3-2-1、自定义断言的核心步骤
自定义路由断言工厂需要继承 AbstractRoutePredicateFactory 类,重写 apply 方法的逻辑。在 apply 方法中可以通过 exchange.getRequest() 拿到 ServerHttpRequest 对象,从而可以获取到请求的参数、请求方式、请求头等信息。
下面就以Query这个断言工厂来看下,断言工厂都需要哪些相关代码内容
1、 必须spring组件 bean
2、类必须加上RoutePredicateFactory作为结尾,比如自定一个自己的断言工厂,名称为:MyPreRoutePredicateFactory;MyPre为自己定义内容,RoutePredicateFactory为必须添加的名称
3、必须继承AbstractRoutePredicateFactory,可以看到内置的这些断言工厂都继承了这个类
4、必须声明静态内部类 声明属性来接收 配置文件中对应的断言的信息
5、需要结合shortcutFieldOrder进行绑定
这样在配置文件中的 Query=name,zhangsan。就可以将name映射到PARAM_KEY,将zhangsan映射到REGEXP_KEY上面。
6、通过apply进行逻辑判断 true就是匹配成功 false匹配失败
3-2-2、创建自定义断言工厂
为了方便演示、仅做一个简单的断言工厂,目标是当application.yml中配置了自定义断言工厂的时候,传入的值必须是jony才运行通过。
3-2-2-1、创建自定义断言工厂
最简单的方式就是,拷贝一个内置的自定义断言工厂,然后再进行修改即可。
下面配置了获取值为test的时候才进行放行。
JonyRoutePredicateFactory.java
package com.jony.predicate;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
@Component
public class JonyRoutePredicateFactory extends AbstractRoutePredicateFactory<JonyRoutePredicateFactory.Config> {
public JonyRoutePredicateFactory() {
super(Config.class);
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return new GatewayPredicate() {
@Override
public boolean test(ServerWebExchange serverWebExchange) {
if(config.getName().equals("test")){
return true;
}
return false;
}
};
}
/**
* 快捷配置
* @return
*/
@Override
public List<String> shortcutFieldOrder() {
return Collections.singletonList("name");
}
public static class Config {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
3-2-2-2、配置application.yml
server:
port: 8088
spring:
application:
name: api-gateway
cloud:
nacos:
discovery:
server-addr: 192.168.253.131:8851
username: nacos
password: nacos
gateway:
routes:
- id: seata-order
uri: lb://seata-order
predicates:
- Jony=test
3-2-2-3、测试
修改配置文件,这样就和自定义断言中的值不一样了。
再次访问如下: