文章导航
摘要 :本文主要介绍了Spring Cloud Gateway的动态路由的简单实现方式。
1.前言 网关中有两个重要的概念,那就是路由配置和路由规则,路由配置是指配置某请求路径路由到指定的目的地址。而路由规则是指匹配到路由配置之后,再根据路由规则进行转发处理。 Spring Cloud Gateway作为所有请求流量的入口,在实际生产环境中为了保证高可靠和高可用,尽量避免重启,需要实现Spring Cloud Gateway动态路由配置。前面章节介绍了Spring Cloud Gateway提供的两种方法去配置路由规则,但都是在Spring Cloud Gateway启动时候,就将路由配置和规则加载到内存里,无法做到不重启网关就可以动态的对应路由的配置和规则进行增加,修改和删除。本篇文章简单介绍如何实现Spring Cloud Gateway的动态路由。
2. Spring Cloud Gateway简单的动态路由实现 Spring Cloud Gateway的官方文档并没有讲如何动态配置,查看 Spring Cloud Gateway的源码,发现在org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint
类中提供了动态配置的Rest接口,但是需要开启Gateway的端点
,而且提供的功能不是很强大。通过参考和GatewayControllerEndpoint相关的代码,可以自己编码实际动态路由配置。 下面通过案例的方式去讲解怎么实现Gateway的动态路由配置。案例工程如ch18-7-gateway所示。
代码地址:https://github.com/SpringCloud/spring-cloud-code/blob/master/ch18-7/ch18-7-gateway
3. 简单动态路由的实现 3.1 新建Maven工程ch18-7-gateway 配置主要的核心依赖如代码清单18-33所示: 代码清单: ch18-7/ch18-7-gateway/pom.xml1
2
3
4
5
6
7
8
9
10
11
12
13
14
<dependencies >
<dependency >
<groupId > org.springframework.cloud</groupId >
<artifactId > spring-cloud-starter-gateway</artifactId >
</dependency >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-webflux</artifactId >
</dependency >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-actuator</artifactId >
</dependency >
</dependencies >
3.2 根据Spring Cloud Gateway的路由模型定义数据传输模型 分别创建GatewayRouteDefinition.java, GatewayPredicateDefinition.java, GatewayFilterDefinition.java这三个类。 (1) 创建路由定义模型
如下代码清单18-34所示: 代码清单 18-34: ch18-7/ch18-7-gateway/src/main/java/cn/springcloud/book/gateway/model/GatewayRouteDefinition.java
1
2
3
4
5
6
7
8
9
10
11
12
13
public class GatewayRouteDefinition {
private String id;
private List<GatewayPredicateDefinition> predicates = new ArrayList<>();
private List<GatewayFilterDefinition> filters = new ArrayList<>();
private String uri;
private int order = 0 ;
}
(2)创建过滤器定义模型
,代码如代码清单18-35所示: 代码清单18-35: ch18-7/ch18-7-gateway/src/main/java/cn/springcloud/book/gateway/model/GatewayFilterDefinition.java
1
2
3
4
5
6
7
public class GatewayFilterDefinition {
private String name;
private Map<String, String> args = new LinkedHashMap<>();
}
(3)路由断言定义模型
,代码如代码清单18-36所示: 代码清单18-36: ch18-7/ch18-7-gateway/src/main/java/cn/springcloud/book/gateway/model/GatewayPredicateDefinition.java
1
2
3
4
5
6
7
public class GatewayPredicateDefinition {
private String name;
private Map<String, String> args = new LinkedHashMap<>();
}
3.3 编写动态路由实现类 编写DynamicRouteServiceImpl并实现ApplicationEventPublisherAware接口,代码如代码清单18-37所示: ch18-37/ch18-7-gateway/src/main/java/cn/springcloud/book/gateway/route/DynamicRouteServiceImpl.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@Service
public class DynamicRouteServiceImpl implements ApplicationEventPublisherAware {
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
private ApplicationEventPublisher publisher;
public String add (RouteDefinition definition) {
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
this .publisher.publishEvent(new RefreshRoutesEvent(this ));
return "success" ;
}
public String update (RouteDefinition definition) {
try {
this .routeDefinitionWriter.delete(Mono.just(definition.getId()));
} catch (Exception e) {
return "update fail,not find route routeId: " +definition.getId();
}
try {
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
this .publisher.publishEvent(new RefreshRoutesEvent(this ));
return "success" ;
} catch (Exception e) {
return "update route fail" ;
}
}
public Mono<ResponseEntity<Object>> delete(String id) {
return this .routeDefinitionWriter.delete(Mono.just(id))
.then(Mono.defer(() -> Mono.just(ResponseEntity.ok().build())))
.onErrorResume(t -> t instanceof NotFoundException, t -> Mono.just(ResponseEntity.notFound().build()));
}
@Override
public void setApplicationEventPublisher (ApplicationEventPublisher applicationEventPublisher) {
this .publisher = applicationEventPublisher;
}
}
3.4 编写Rest接口 编写RouteController类的提供Rest接口,用于动态路由配置。代码如代码清单18-38所示: 代码清单 18-38: ch18-7/ch18-7-gateway/src/main/java/cn/springcloud/book/gateway/controller/RouteController.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@RestController
@RequestMapping ("/route" )
public class RouteController {
@Autowired
private DynamicRouteServiceImpl dynamicRouteService;
@PostMapping ("/add" )
public String add (@RequestBody GatewayRouteDefinition gwdefinition) {
try {
RouteDefinition definition = assembleRouteDefinition(gwdefinition);
return this .dynamicRouteService.add(definition);
} catch (Exception e) {
e.printStackTrace();
}
return "succss" ;
}
@DeleteMapping ("/routes/{id}" )
public Mono<ResponseEntity<Object>> delete(@PathVariable String id) {
return this .dynamicRouteService.delete(id);
}
@PostMapping ("/update" )
public String update (@RequestBody GatewayRouteDefinition gwdefinition) {
RouteDefinition definition = assembleRouteDefinition(gwdefinition);
return this .dynamicRouteService.update(definition);
}
}
3.5 配置application.yml文件 在application.yml文件配置应用的配置信息,并开启Spring Cloud Gateway对外提供的端点Rest接口。代码如代码清单18-39所示: 代码清单 18-39: ch18-7/ch18-7-gateway/src/main/resources/application.yml 配置输出日志如下所示:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
logging:
level:
org.springframework.cloud.gateway: TRACE
org.springframework.http.server.reactive: DEBUG
org.springframework.web.reactive: DEBUG
reactor.ipc.netty: DEBUG
management:
endpoints:
web:
exposure:
include: '*'
security:
enabled: false
3.6 启动ch18-7-gateway应用测试 (1) 启动ch18-7-gateway应用之后,由于开启了端点,首先打开浏览器访问端点URL:http://localhost:8080/actuator/gateway/routes ,查看路由信息返回为空,如下图所示:
(2)打开PostMan,访问http://localhost:8080/route/add , 发起Post请求,如下图所示,返回success说明向Gateway增加路由配置成功。
然后再打开PostMan访问端点URL:http://localhost:8080/actuator/gateway/routes , 查看路由信息返回如下图所示,可以看到已经添加的路由配置。
(3) 打开浏览器访问http://localhost:8080/jd , 可以正常转发https://www.jd.com/对应的京东商城首页。 (4) 通过访问http://localhost:8080/route/update , 对id为jd_route的路由更新配置,如下图所示:
然后再访问路由端点URL,发现路由配置已经被更新,如下图所示:
然后通过浏览器访问http://localhost:8080/taobao ,可以成功转发到淘宝网。 (5) 通过访问http: //localhost:8080/route/delete/jd_route,其中的id为路由对应的id,删除路由结果如下图所示:
4.Spring Cloud Gateway推荐文章 Spring Cloud Gateway中的权重路由 Spring Cloud Gateway中的GatewayFilter和GlobalFilter Spring Cloud Gateway只有Pre和POST两种类型的Filter Spring Cloud Gateway基于服务发现的默认路由规则 Spring Cloud Gateway的Before路由断言工厂 Spring Cloud Gateway的After路由断言工厂 Spring Cloud Gateway揭秘之处理请求流程 Spring Cloud Gateway入门案例
5.《重新定义Spring Cloud实战》中的Spring Cloud Gateway 第17章Spring Cloud Gateway上篇399 17.1 Spring Cloud Gateway概述399 17.1.1 什么是Spring Cloud Gateway399 17.1.2 Spring Cloud Gateway的核心概念399 17.2 Spring Cloud Gateway的工作原理400 17.3 Spring Cloud Gateway入门案例401 17.4 Spring Cloud Gateway的路由断言404 17.4.1 After路由断言工厂404 17.4.2 Before路由断言工厂406 17.4.3 Between路由断言工厂406 17.4.4 Cookie路由断言工厂407 17.4.5 Header路由断言工厂408 17.4.6 Host路由断言工厂410 17.4.7 Method路由断言工厂411 17.4.8 Query路由断言工厂411 17.4.9 RemoteAddr路由断言工厂412 17.5 Spring Cloud Gateway的内置Filter413 17.5.1 AddRequestHeader过滤器工厂413 17.5.2 AddRequestParameter过滤器413 17.5.3 RewritePath过滤器414 17.5.4 AddResponseHeader过滤器415 17.5.5 StripPrefix过滤器416 17.5.6 Retry过滤器417 17.5.7 Hystrix过滤器418 17.6 本章小结420 第18章 Spring Cloud Gateway下篇421 18.1 Gateway基于服务发现的路由规则421 18.1.1 Gateway的服务发现路由概述421 18.1.2 服务发现的路由规则案例422 18.2 Gateway Filter和Global Filter425 18.2.1 Gateway Filter和Global Filter概述425 18.2.2 自定义Gateway Filter案例425 18.2.3 自定义Global Filter案例427 18.3 Spring Cloud Gateway实战428 18.3.1 Spring Cloud Gateway权重路由428 18.3.2 Spring Cloud Gateway中Https的使用技巧431 18.3.3 Spring Cloud Gateway集成Swagger436 18.3.4 Spring Cloud Gateway限流442 18.3.5 Spring Cloud Gateway的动态路由450 18.4 Spring Cloud Gateway源码篇458 18.4.1 Spring Cloud Gateway的处理流程458 18.4.2 Gateway中ServerWebExchange构建分析459 18.4.3 DispatcherHandler源码分析460 18.4.4 RoutePredicateHandlerMapping源码分析461 18.4.5 FilteringWebHandler源码分析462 18.4.6 执行Filter源码分析463 18.5 本章小结465
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
├── ch17-1
│ ├── ch17-1-1-gateway
│ ├── ch17-1-2-gateway
│ ├── ch17-1.iml
│ └── pom.xml
├── ch17-2
│ ├── ch17-2-1-gateway
│ ├── ch17-2-2-gateway
│ ├── ch17-2-3-gateway
│ ├── ch17-2-4-gateway
│ ├── ch17-2-5-gateway
│ ├── ch17-2-6-gateway
│ ├── ch17-2-7-gateway
│ ├── ch17-2-8-gateway
│ ├── ch17-2-9-gateway
│ ├── ch17-2-service
│ ├── ch17-2.iml
│ └── pom.xml
├── ch17-3
│ ├── ch17-3-1-gateway
│ ├── ch17-3-2-gateway
│ ├── ch17-3-3-gateway
│ ├── ch17-3-4-gateway
│ ├── ch17-3-5-gateway
│ ├── ch17-3-6-gateway
│ ├── ch17-3-7-gateway
│ ├── ch17-3-service
│ ├── ch17-3.iml
│ └── pom.xml
├── ch18-1
│ ├── ch18-1-consumer
│ ├── ch18-1-eureka
│ ├── ch18-1-gateway
│ ├── ch18-1-provider
│ ├── ch18-1.iml
│ └── pom.xml
├── ch18-2
│ ├── ch18-2-gateway
│ ├── ch18-2-provider
│ ├── ch18-2.iml
│ ├── pom.xml
│ └── reademe.txt
├── ch18-3
│ ├── ch18-3-gateway
│ ├── ch18-3-provider
│ ├── ch18-3.iml
│ └── pom.xml
├── ch18-4
│ ├── ch18-4-eureka
│ ├── ch18-4-gateway-https
│ ├── ch18-4-service-a
│ ├── ch18-4-service-b
│ ├── ch18-4.iml
│ ├── pom.xml
│ └── reademe.md
├── ch18-5
│ ├── ch18-5-eureka
│ ├── ch18-5-gateway
│ ├── ch18-5-service
│ ├── ch18-5.iml
│ └── pom.xml
├── ch18-6
│ ├── ch18-6-1-gateway
│ ├── ch18-6-2-gateway
│ ├── ch18-6-3-gateway
│ ├── ch18-6-provider
│ ├── ch18-6.iml
│ └── pom.xml
├── ch18-7
│ ├── ch18-7-gateway
│ ├── ch18-7.iml
│ ├── pom.xml
│ └── readme.md
Spring Cloud Gateway所有示例代码地址:https://github.com/SpringCloud/spring-cloud-code
如果您觉得文章不错,可以打赏我喝一杯咖啡!
赏
微信打赏
支付宝打赏