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.xml

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-gateway</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework.boot</groupId>
  8. <artifactId>spring-boot-starter-webflux</artifactId>
  9. </dependency>
  10. <dependency>
  11. <groupId>org.springframework.boot</groupId>
  12. <artifactId>spring-boot-starter-actuator</artifactId>
  13. </dependency>
  14. </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. public class GatewayRouteDefinition {
  2. //路由的Id
  3. private String id;
  4. //路由断言集合配置
  5. private List<GatewayPredicateDefinition> predicates = new ArrayList<>();
  6. //路由过滤器集合配置
  7. private List<GatewayFilterDefinition> filters = new ArrayList<>();
  8. //路由规则转发的目标uri
  9. private String uri;
  10. //路由执行的顺序
  11. private int order = 0;
  12. //此处省略get和set方法
  13. }

(2)创建过滤器定义模型,代码如代码清单18-35所示:
代码清单18-35: ch18-7/ch18-7-gateway/src/main/java/cn/springcloud/book/gateway/model/GatewayFilterDefinition.java

  1. public class GatewayFilterDefinition {
  2. //Filter Name
  3. private String name;
  4. //对应的路由规则
  5. private Map<String, String> args = new LinkedHashMap<>();
  6. //此处省略Get和Set方法
  7. }

(3)路由断言定义模型,代码如代码清单18-36所示:
代码清单18-36: ch18-7/ch18-7-gateway/src/main/java/cn/springcloud/book/gateway/model/GatewayPredicateDefinition.java

  1. public class GatewayPredicateDefinition {
  2. //断言对应的Name
  3. private String name;
  4. //配置的断言规则
  5. private Map<String, String> args = new LinkedHashMap<>();
  6. //此处省略Get和Set方法
  7. }

3.3 编写动态路由实现类

编写DynamicRouteServiceImpl并实现ApplicationEventPublisherAware接口,代码如代码清单18-37所示: ch18-37/ch18-7-gateway/src/main/java/cn/springcloud/book/gateway/route/DynamicRouteServiceImpl.java

  1. @Service
  2. public class DynamicRouteServiceImpl implements ApplicationEventPublisherAware {
  3. @Autowired
  4. private RouteDefinitionWriter routeDefinitionWriter;
  5. private ApplicationEventPublisher publisher;
  6. //增加路由
  7. public String add(RouteDefinition definition) {
  8. routeDefinitionWriter.save(Mono.just(definition)).subscribe();
  9. this.publisher.publishEvent(new RefreshRoutesEvent(this));
  10. return "success";
  11. }
  12. //更新路由
  13. public String update(RouteDefinition definition) {
  14. try {
  15. this.routeDefinitionWriter.delete(Mono.just(definition.getId()));
  16. } catch (Exception e) {
  17. return "update fail,not find route routeId: "+definition.getId();
  18. }
  19. try {
  20. routeDefinitionWriter.save(Mono.just(definition)).subscribe();
  21. this.publisher.publishEvent(new RefreshRoutesEvent(this));
  22. return "success";
  23. } catch (Exception e) {
  24. return "update route fail";
  25. }
  26. }
  27. //删除路由
  28. public Mono<ResponseEntity<Object>> delete(String id) {
  29. return this.routeDefinitionWriter.delete(Mono.just(id))
  30. .then(Mono.defer(() -> Mono.just(ResponseEntity.ok().build())))
  31. .onErrorResume(t -> t instanceof NotFoundException, t -> Mono.just(ResponseEntity.notFound().build()));
  32. }
  33. @Override
  34. public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
  35. this.publisher = applicationEventPublisher;
  36. }
  37. }

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. @RestController
  2. @RequestMapping("/route")
  3. public class RouteController {
  4. @Autowired
  5. private DynamicRouteServiceImpl dynamicRouteService;
  6. //增加路由
  7. @PostMapping("/add")
  8. public String add(@RequestBody GatewayRouteDefinition gwdefinition) {
  9. try {
  10. RouteDefinition definition = assembleRouteDefinition(gwdefinition);
  11. return this.dynamicRouteService.add(definition);
  12. } catch (Exception e) {
  13. e.printStackTrace();
  14. }
  15. return "succss";
  16. }
  17. //删除路由
  18. @DeleteMapping("/routes/{id}")
  19. public Mono<ResponseEntity<Object>> delete(@PathVariable String id) {
  20. return this.dynamicRouteService.delete(id);
  21. }
  22. //更新路由
  23. @PostMapping("/update")
  24. public String update(@RequestBody GatewayRouteDefinition gwdefinition) {
  25. RouteDefinition definition = assembleRouteDefinition(gwdefinition);
  26. return this.dynamicRouteService.update(definition);
  27. }
  28. }

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. logging:
  3. level:
  4. org.springframework.cloud.gateway: TRACE
  5. org.springframework.http.server.reactive: DEBUG
  6. org.springframework.web.reactive: DEBUG
  7. reactor.ipc.netty: DEBUG
  8. #开启端点
  9. management:
  10. endpoints:
  11. web:
  12. exposure:
  13. include: ‘*‘
  14. security:
  15. 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,删除路由结果如下图所示:

原文地址:https://www.cnblogs.com/7788IT/p/11361125.html

时间: 2024-11-08 00:10:29

Spring Cloud Gateway的动态路由实现的相关文章

Spring Cloud Alibaba | Nacos动态网关路由

Spring Cloud Alibaba | Gateway基于Nacos动态网关路由 本篇实战所使用Spring有关版本: SpringBoot:2.1.7.RELEASE Spring Cloud:Greenwich.SR2 Spring CLoud Alibaba:2.1.0.RELEASE 前面几篇文章我们介绍了<Nacos服务注册与发现>和<Nacos配置管理>,还没看过的小伙伴们快去看一下,本篇文章是建立在这两篇文章基础上的一次实战. 背景介绍 在Spring Clou

Spring Cloud Gateway初体验

前段时间项目上打算使用gateway替换掉zuul1.0于是我简单的体验了一下. gateway是什么:Spring Cloud Gateway是Spring官方基于Spring 5.0,Spring Boot 2.0和Project Reactor等技术开发的网关,Spring Cloud Gateway旨在为微服务架构提供一种简单而有效的统一的API路由管理方式.这里需要注意一下gateway使用的netty+webflux实现,不要加入web依赖,需要加入webflux依赖. gatewa

Spring Cloud Gateway服务网关

原文:https://www.cnblogs.com/ityouknow/p/10141740.html Spring 官方最终还是按捺不住推出了自己的网关组件:Spring Cloud Gateway ,相比之前我们使用的 Zuul(1.x) 它有哪些优势呢?Zuul(1.x) 基于 Servlet,使用阻塞 API,它不支持任何长连接,如 WebSockets,Spring Cloud Gateway 使用非阻塞 API,支持 WebSockets,支持限流等新特性. Spring Clou

基于Spring cloud gateway定制的微服务网关

在构建微服务的架构体系过程中,API网关是一个非常重要的组件.那我们应该怎样实现一个微服务API网关,本文主要介绍Spring Cloud Gateway的功能,以及如何基于Spring Cloud Gateway定制自己的网关. Spring Cloud GatewaySpring Cloud Gateway提供的是一个用于在Spring MVC之上构建API网关的library,它的目标是提供一种简单而有效的方式路由API请求,它提供了一个切面,主要关注:安全.监控/metrics.弹性伸缩

跟我学SpringCloud | 第十二篇:Spring Cloud Gateway初探

SpringCloud系列教程 | 第十二篇:Spring Cloud Gateway初探 Springboot: 2.1.6.RELEASE SpringCloud: Greenwich.SR1 如无特殊说明,本系列教程全采用以上版本 前面我们在聊服务网关Zuul的时候提到了Gateway,那么Zuul和Gateway都是服务网关,这两个有什么区别呢? 1. Zuul和Gateway的恩怨情仇 1.1 背景 Zuul是Netflix开源的一个项目,Spring只是将Zuul集成在了Spring

Spring Cloud Gateway - 扩展

[TOC] Spring Cloud Gateway的监控端点 说到监控,就应该能想到Spring Boot Actuator.而Spring Cloud Gateway基于Actuator提供了许多的监控端点.只需要在项目中添加spring-boot-starter-actuator依赖,并将 gateway 端点暴露,即可获得若干监控端点.配置示例: management: endpoints: web: exposure: include: gateway # 或者配置"*"暴露

Spring Cloud gateway 网关服务二 断言、过滤器

微服务当前这么火爆的程度,如果不能学会一种微服务框架技术.怎么能升职加薪,增加简历的筹码?spring cloud 和 Dubbo 需要单独学习.说没有时间?没有精力?要学俩个框架?而Spring Cloud alibaba只需要你学会一个就会拥有俩种微服务治理框架技术.何乐而不为呢?加油吧!骚猿年 上一篇我们讲述了gateway 的路由功能其实也类似与zuul服务的路由转发. 今天主要讲一下断言机制. 内置的断言工厂 介绍 Spring Cloud Gateway将路由作为Spring Web

Spring Cloud Gateway初探

Zuul和Gateway的恩怨情仇 1.1 背景 Zuul是Netflix开源的一个项目,Spring只是将Zuul集成在了Spring Cloud中.而Spring Cloud Gateway是Spring Cloud的一个子项目. 还有一个版本的说法是Zuul2的连续跳票和Zuul1的性能并不是很理想,从而催生了Spring Cloud Gateway. 1.2 性能比较 网上很多地方都说Zuul是阻塞的,Gateway是非阻塞的,这么说是不严谨的,准确的讲Zuul1.x是阻塞的,而在2.x

微服务下使用网关 Spring Cloud Gateway

Spring Cloud Gateway 工作原理 客户端向 Spring Cloud Gateway 发出请求,如果请求与网关程序定义的路由匹配,则将其发送到网关 Web 处理程序,此处理程序运行特定的请求过滤器链. 过滤器之间用虚线分开的原因是过滤器可能会在发送代理请求之前或之后执行逻辑.所有 "pre" 过滤器逻辑先执行,然后执行代理请求,代理请求完成后,执行 "post" 过滤器逻辑. 如何启动 Spring Cloud Gateway 1.新建 Maven