Spring Cloud Gateway-动态路由器实现

1,588 阅读2分钟

1 路由配置的两种方式

  • yml文件配置

    yml文件配置可以参照官网的配置方式,精简的配置例子如下:

    spring:
      cloud:
        gateway:
          routes:
          - id: after_route
            uri: https://example.org
            predicates:
            - Cookie=mycookie,mycookievalue
    

    完全的例子:

    spring:
      cloud:
        gateway:
          routes:
          - id: after_route
            uri: https://example.org
            predicates:
            - name: Cookie
              args:
                name: mycookie
                regexp: mycookievalue
    

    Spring Cloud Gateway官网的配置

  • 代码

    @SpringBootApplication
    public class DemogatewayApplication {
    	@Bean
    	public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
    		return builder.routes()
    			.route("path_route", r -> r.path("/get")
    				.uri("http://httpbin.org"))
    			.route("host_route", r -> r.host("*.myhost.org")
    				.uri("http://httpbin.org"))
    			.route("rewrite_route", r -> r.host("*.rewrite.org")
    				.filters(f -> f.rewritePath("/foo/(?<segment>.*)", "/${segment}"))
    				.uri("http://httpbin.org"))
    			.route("hystrix_route", r -> r.host("*.hystrix.org")
    				.filters(f -> f.hystrix(c -> c.setName("slowcmd")))
    				.uri("http://httpbin.org"))
    			.route("hystrix_fallback_route", r -> r.host("*.hystrixfallback.org")
    				.filters(f -> f.hystrix(c -> c.setName("slowcmd").setFallbackUri("forward:/hystrixfallback")))
    				.uri("http://httpbin.org"))
    			.route("limit_route", r -> r
    				.host("*.limited.org").and().path("/anything/**")
    				.filters(f -> f.requestRateLimiter(c -> c.setRateLimiter(redisRateLimiter())))
    				.uri("http://httpbin.org"))
    			.build();
    	}
    }
    

    以编程的方式配置。

以上两种都是将路由写死,没有进行动态的加载。下面来看一下如何动态添加路由器。

2 动态路由

spring cloud gateway的源码版本 2.2.6.RELEASE

动态路由可以通过配置来实现动态的加载。首先来通过源码分析一下路由的初始化过程。

默认是从配置文件加载。这个也是官网的配置。路由的定义最终用 RouteDefinition 类进行封装。项目启动所有的路由都被加载装配,并且存到了内存中:

添加的数据存储在内存中。在没有用户自定义的情况下会从文件配置中加载和内存中加载。在刚刚启动网关项目的内存总是没有任何路由的定义的。

只要实现RouteDefinitionRepository接口就能自定义加载存储位置了。

如何添加了?在Spring Cloud gateway官网上有现成的接口.

actuator api中包含了gateway的动态添加接口和查询接口:

当然也可以参照 GatewayControllerEndpoint 自己实现

本人比较懒用现成的就可以。结合上面的实现的存储位置就能实现动态的添加路由器了。

注意: 用接口/gateway/routes/{id_route_to_create} (POST)添加完成路由后,你立马调用/actuator/gateway/routes/{id} (GET) 是获取不到刚添加的路由。原因在于路由都是从缓存中获取。添加后需要调用/actuator/gateway/refresh (POST) 清除缓存。这样就能重新加载缓存获取到新加的路由器信息了。