1

我目前正在使用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();
}

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

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

谢谢

4

4 回答 4

5

每当您希望动态更新路由时,请发送 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

于 2018-07-24T12:49:31.127 回答
3

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

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();
    }
}
于 2020-05-22T14:08:13.213 回答
1

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

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

/actuator/gateway/refresh

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

于 2018-06-12T08:18:41.373 回答
0

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

于 2018-06-12T08:57:15.747 回答