【问题标题】:Persisting Spring Cloud Gateway Routes in Database在数据库中持久化 Spring Cloud Gateway 路由
【发布时间】:2018-11-21 11:21:49
【问题描述】:

我目前正在使用spring cloud gateway项目搭建简单的api网关,计划将路由持久化到mongodb中,然后刷新,这样新的路由就可以使用了。我做了一些简单的事情来从 mongo 获取我的路线。

@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder){
    List<CreateAPIRequest> apiRequestList = repository.findAll();
    RouteLocatorBuilder.Builder routeLocator = builder.routes();
    for (CreateAPIRequest request: apiRequestList) {
        routeLocator
        .route(r-> {
              r.path("/"+request.getProxy().getListenPath())
             .filters(f->f.stripPrefix(1))
             .uri(request.getProxy().getTargetUrl()) 
        });
    }
    return routeLocator.build();
}

我能够在数据库中创建新路由,但无法即时刷新。

我需要了解如何即时刷新路线。

谢谢

【问题讨论】:

    标签: spring-boot spring-cloud spring-cloud-gateway


    【解决方案1】:

    只要您希望动态更新路由,就发送 RefreshRoutesEvent。以下组件实现了事件发送功能。

    @Component
    public class GatewayRoutesRefresher implements ApplicationEventPublisherAware {
    
        ApplicationEventPublisher publisher;
    
        @Override
        public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
            publisher = applicationEventPublisher;
        }
    
        public void refreshRoutes() {
            publisher.publishEvent(new RefreshRoutesEvent(this));
        }
    }
    

    这是一个示例,展示了如何使用上面的组件:

    @Autowired
    GatewayRoutesRefresher gatewayRoutesRefresher;
    ...
    public void buildRoutes() {
        // build your routes basing on your db entries then refresh the routes in gateway
        ...
        gatewayRoutesRefresher.refreshRoutes();
    }
    

    您可以通过查看以下项目代码找到更完整的概念图:https://github.com/botorabi/HomieCenter

    【讨论】:

      【解决方案2】:

      SCG(Spring Cloud Gateway)已经提供RouteDefinitionRepository,你可以自己编写RouteDefinitionRepository,并实现RouteDefinitionRepository覆盖getRouteDefinitions方法。

      可以参考这个类:InMemoryRouteDefinitionRepository

      例如:

      @Service
      public class MongodbDefinitionRepository implements RouteDefinitionRepository {
      
          @Autowired
          private RouteConfigDao routeConfigDao;
      
          @Override
          public Flux<RouteDefinition> getRouteDefinitions() {
              // todo 
              List<RouteDefinition> routeConfigs = routeConfigDao.findAll();
              return Flux.fromIterable(routeConfigs);
          }
      
          @Override
          public Mono<Void> save(Mono<RouteDefinition> route) {
              return route.flatMap(routeDefinition -> {
                  // todo 
                  return Mono.empty();
              });
          }
      
          @Override
          public Mono<Void> delete(Mono<String> routeId) {
              return routeId.flatMap(id -> {
                  // todo 
                  int delete = routeConfigDao.delete(routeId);
                  if (delete > 0) {
                      return Mono.empty();
                  }
                  return Mono.defer(() -> Mono.error(new Exception("delete route definition error, routeId:" + routeId)));
              });
          }
      }
      
      

      如何即时刷新路线

      1. 启用执行器

      把它放在你的application.yml

      management:
        endpoints:
          web:
            exposure:
              include: gateway
      

      发布http://ip:port/actuator/gateway/refresh

      1. 发布 RefreshRoutesEvent
      @Service
      public class MyPublishBiz implements ApplicationEventPublisherAware {
          protected ApplicationEventPublisher publisher;
      
          @Override
          public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
              this.publisher = publisher;
          }
      
          public Mono<Void> refresh() {
              this.publisher.publishEvent(new RefreshRoutesEvent(this));
              return Mono.empty();
          }
      }
      

      【讨论】:

      • 您好,请问如何在我的课堂上添加RouteConfigDao?它不是 SCG 的类型,不是吗?
      【解决方案3】:

      我很快就去了 repo 和未解决的问题。

      目前看来,刷新路线的唯一方法是从 Actuator 通过:

      /actuator/gateway/refresh
      

      您可以在这里查看讨论:https://github.com/spring-cloud/spring-cloud-gateway/issues/43

      【讨论】:

        【解决方案4】:

        您可以使用Consul 代替 mongo 来持久化您的路由定义吗?然后,对执行器刷新的简单 POST 调用将即时重新加载您的路由定义。

        【讨论】:

          猜你喜欢
          • 2019-08-03
          • 2019-03-31
          • 2023-01-21
          • 1970-01-01
          • 2019-09-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-05-16
          相关资源
          最近更新 更多