Spring Cloud Gateway——实现路由动态修改

Posted 不去天涯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Cloud Gateway——实现路由动态修改相关的知识,希望对你有一定的参考价值。

动态路由修改

当我们看了Spring Cloud Gateway的示例代码,和一些网上的入门教程之后,会发现大多是Spring Cloud Gateway — 网关基本功能API暴露说道的三种方法:1.本地配置文件;2.java代码builder.routes().route().build(); 3.服务自动发现。

服务自动发现方法能够做到后端服务ip变化时自动更新,能够做到上游服务的动态。另外两种方式都是纯静态,需要重新启动网关服务修改才能生效。

上述方式都不能完全满足生产需要,一般来说作为生产上的通用网关要求有路由动态修改能力,不重启网关服务即可即使生效。无论是新增路由、或者是修改路由的过滤规则,添加过滤器都可以不重启网关生效。

内置的动态路由

Spring Cloud Gateway内置了一个动态路由类InMemoryRouteDefinitionRepository。这是一个使用内存存储路由的类,支持acurator接口对路由进行增删改查,但是当网关重启之后所有的内存路由都会消失,也就是说它没有持久化能力。

虽然InMemoryRouteDefinitionRepository没有达到生产级动态路由修改的需求,但是它提供了一种思路,起到了示例作用。如果需要实现自己的可持久化动态路由,可以仿照InMemoryRouteDefinitionRepository的路由解析加载能力,以及更新方式实现在即的动态路由。

基于分布式配置的动态路由

基于分布式配置可能是一种最简单便捷的路由动态修改能力了,这里展示基于spring cloud config实现Spring Cloud Gateway动态路由修改。

/**
 * a route definition locator, that locate route definition from remote config server or local properties file.
 * route definition is json value, not yaml value, e.g.
 * "route-definitions=[\\"id\\": \\"websocket_test\\",\\"uri\\": \\"ws://localhost:9000\\",\\"order\\": 9000,\\"predicates\\":[\\"Path=/echo\\"],\\"filters\\":[\\"AddRequestHeader=x-tt-token, 123456\\"]]"
 * or
 * "route-definitions=[\\"id\\": \\"websocket_test\\",\\"uri\\": \\"ws://localhost:9000\\",\\"order\\": 9000,\\"predicates\\":[\\"name\\":\\"Path\\", \\"args\\":\\"_genkey_0\\":\\"/echo\\"],\\"filters\\":[\\"name\\":\\"AddRequestHeader\\", \\"args\\":\\"_genkey_0\\":\\"x-tt-token\\",\\"_genkey_1\\":\\"123456\\"]]"
 *
 * compare to spring cloud gateway's default InMemoryRouteDefinitionRepository, route definitions could be loaded when program's startup.
 *
 * to do this, there is another way. define a bean and load remote route definitions to InMemoryRouteDefinitionRepository when program's startup.
 * otherwise, you should implement ApplicationListener<ApplicationEvent>. when refresh event emited, remote route definitions should be reloaded
 * into InMemoryRouteDefinitionRepository.
 */
public class ConfigServerRouteDefinitionLocator implements RouteDefinitionLocator 
    @Value("$route-definitions")
    private String routeDefinitions;//a json string, contains route definition lists

    @Override
    public Flux<RouteDefinition> getRouteDefinitions() 
        ObjectMapper mapper = new ObjectMapper();
        List<RouteDefinition> rdList = null;
        try 
            System.out.println(routeDefinitions);
            rdList = mapper.readValue(routeDefinitions, new TypeReference<List<RouteDefinition>>()  );
            return Flux.fromArray(rdList.toArray(new RouteDefinition[]));
         catch (JsonProcessingException e) 
            e.printStackTrace();
        

        return Flux.empty();
    

方法很简单,只需要在config server里增加一个路由的配置项即可。config server可以调用Spring Cloud Gateway的路由更新接口/refresh,路由配置就会自动更新。

如果要实现更复杂的控制逻辑,比如路由配置的路由校验、版本控制、灰度发布等其他功能,可以在定义自己的refresh接口和管理后台进行控制。

其他方式

如果时间允许,可以使用其他存储方式实现路由动态修改能力。可以参考以下文章:

基于Redis实现动态路由修改
基于Redis实现动态路由修改-其中的金丝雀是对上游的金丝雀发布,不是对网关自身的金丝雀控制,这种用法一般不太常见

以上是关于Spring Cloud Gateway——实现路由动态修改的主要内容,如果未能解决你的问题,请参考以下文章

Spring Cloud-Gateway网关

spring cloud gateway 如何工作

Spirng Cloud Gateway中通过Spring security + WebFlux 实现权限认证

spring cloud gateway 某些路由中跳过全局过滤器

Spring Cloud Gateway的动态路由实现

spring cloud gateway + oauth2 实现网关统一权限认证