在数据库中保留Spring Cloud Gateway路由

时间:2018-06-12 06:43:20

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

我目前正在使用spring cloud网关项目构建简单的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();
}

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

我需要了解如何动态刷新路线。

由于

4 个答案:

答案 0 :(得分:2)

RouteDefinitionRepository已提供了SCG(Spring Cloud Gateway),您可以编写自己的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

POST 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();
    }
}

答案 1 :(得分: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 :(得分:0)

我快速回到了回购和开放的问题。

目前似乎刷新路线的唯一方法是从Actuator通过:

/actuator/gateway/refresh

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

答案 3 :(得分:0)

您是否可以使用Consul来保留路由定义而不是mongo。然后,对执行器刷新的简单POST调用将动态重新加载您的路径定义。