• 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,删除路由结果如下图所示:

     

  • 相关阅读:
    Jasper 常用知识点总结
    Linux
    搭建spring项目,无法创建RequestMappingHandlerMapping异常
    pom.xml文件设置
    MySQL的常用JSON函数
    SQL中的条件判断语句(case when zhen if,ifnull)用法
    sql查询原理
    sql积累
    Linux常用命令大全
    mysql中group by 的用法解析
  • 原文地址:https://www.cnblogs.com/7788IT/p/11361125.html
Copyright © 2020-2023  润新知