当前位置: 代码迷 >> 综合 >> spring-cloud-gateway(2)--->spring-cloud-gateway如何实现动态路由
  详细解决方案

spring-cloud-gateway(2)--->spring-cloud-gateway如何实现动态路由

热度:76   发布时间:2023-10-24 14:36:07.0

1、什么是动态路由,也就是在网关服务不停机的状态下,动态的添加route或者删除route,这就是动态路由的定义,我们在前面实战zuul的时候也提到过这个问题,当时的实现动态路由的方式是,使用配置中心进行route的配置,然后在增删路由的时候,使用actuator进行手动刷新。 当然在 spring-cloud-gateway中也可以这样实现,但是 spring-cloud-gateway中还为我们提供了另一种方式,那就是直接使用actuator API,官网地址如下:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#actuator-api

 

2、使用 spring-cloud-gateway 的 actuator API来实现动态路由实战:

      2.1、在项目中引入spring-boot-starter-actuator的依赖:

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>

       2.2、暴露端点:

management:endpoints:web:exposure:include: "*"

        2.3、使用 spring-cloud-gateway 的 actuator API来查看已经配置的路由信息,地址为 http://网关服务ip:网关服务地址/actuator/gateway/routes   可得出已经配置的路由列表:

[{"predicate": "Paths: [/gateway-server/**], match trailing slash: true","metadata": {"jmx.port": "62460","management.port": "6060"},"route_id": "ReactiveCompositeDiscoveryClient_GATEWAY-SERVER","filters": ["[[RewritePath /gateway-server/(?<remaining>.*) = '/${remaining}'], order = 1]"],"uri": "lb://GATEWAY-SERVER","order": 0},{"predicate": "Paths: [/orderapi/**], match trailing slash: true","route_id": "orderapi","filters": ["[[StripPrefix parts = 1], order = 1]","[[Hystrix name = 'fallbackcmd', fallback = forward:/orderapi/order/mock], order = 2]","[org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactory$$Lambda$878/488624810@2b12211e, order = 3]"],"uri": "http://localhost:7070","order": 0},{"predicate": "Paths: [/userapi/**], match trailing slash: true","route_id": "userapi","filters": ["[[StripPrefix parts = 1], order = 1]"],"uri": "lb://user-service","order": 0},{"predicate": "(Paths: [/customer/predicate/**], match trailing slash: true && com.wzy.gateway.AuthRoutePredicateFactory$1@27f952b1)","route_id": "costomer_predicate","filters": ["[[StripPrefix parts = 2], order = 1]"],"uri": "http://www.baidu.com:80","order": 0}
]

         2.4、使用 spring-cloud-gateway 的 actuator API来添加路由:

                 请求地址:http://localhost:6060/actuator/gateway/routes/api_route

                 请求方式:post   application/json

                 入参格式:

{"id": "first_route","predicates": [{"name": "Path","args": {"_genkey_0": "/api1"}}],"filters": [{"name": "StripPrefix","args": {"_genkey_0": 1}}],"uri": "https://www.baidu.com","order": 0
}

           添加完成后再次查看路由列表,如下:

[{"predicate": "Paths: [/gateway-server/**], match trailing slash: true","metadata": {"jmx.port": "62818","management.port": "6060"},"route_id": "ReactiveCompositeDiscoveryClient_GATEWAY-SERVER","filters": ["[[RewritePath /gateway-server/(?<remaining>.*) = '/${remaining}'], order = 1]"],"uri": "lb://GATEWAY-SERVER","order": 0},{"predicate": "Paths: [/orderapi/**], match trailing slash: true","route_id": "orderapi","filters": ["[[StripPrefix parts = 1], order = 1]","[[Hystrix name = 'fallbackcmd', fallback = forward:http://localhost:6060/fallback], order = 2]","[org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactory$$Lambda$878/1456947885@4c8a8fa0, order = 3]"],"uri": "http://localhost:7070","order": 0},{"predicate": "Paths: [/userapi/**], match trailing slash: true","route_id": "userapi","filters": ["[[StripPrefix parts = 1], order = 1]"],"uri": "lb://user-service","order": 0},{"predicate": "(Paths: [/customer/predicate/**], match trailing slash: true && com.wzy.gateway.AuthRoutePredicateFactory$1@2ce02e80)","route_id": "costomer_predicate","filters": ["[[StripPrefix parts = 2], order = 1]"],"uri": "http://www.baidu.com:80","order": 0},{"predicate": "Paths: [/api1], match trailing slash: true","route_id": "api_route","filters": ["[[StripPrefix parts = 1], order = 1]"],"uri": "https://www.baidu.com:443","order": 0}
]

               可见我们添加的路由api_route已经添加进去了,其他的删除的接口也都有。

 

3、spring-cloud-gateway 的 actuator API来实现动态route的扩展:

      上面我们讲解了使用 actuator API来实现动态路由的实战,接下来我们来针对这种方式进行扩展,为什么要扩展呢?原因就是actuator API来实现动态路的方式,在默认情况下是没有之持久化的,也就是说一旦重启网关服务的话,动态添加的路由就没有了,因此我们需要进行扩展。

       我们就实现使用redis来保存路由信息吧,实现方式如下,在spring-cloud-gateway中提供了一个接口 RouteDefinitionRepository 路由定义仓库,类图如下:

             

            默认值提供了存在在内存中的仓库。

        接下来我们来实现存储在redis中的实现类:

@Component
public class RedisRouteDefRepository implements RouteDefinitionRepository {public static final String GATEWAY_ROUTE_REDIS_KEY = "gateway_route_redis_key";@Autowiredprivate StringRedisTemplate redisTemplate;@Overridepublic Flux<RouteDefinition> getRouteDefinitions() {List<RouteDefinition> list = new ArrayList <>();redisTemplate.opsForHash().values(GATEWAY_ROUTE_REDIS_KEY).stream().forEach(route->{list.add(JSON.parseObject(route.toString(), RouteDefinition.class));});return Flux.fromIterable(list);}@Overridepublic Mono<Void> save(Mono <RouteDefinition> route) {return route.flatMap(routeDefinition ->{redisTemplate.opsForHash().put(GATEWAY_ROUTE_REDIS_KEY, routeDefinition.getId(), JSON.toJSONString(routeDefinition));return Mono.empty();});}@Overridepublic Mono <Void> delete(Mono <String> routeId) {return routeId.flatMap(id->{redisTemplate.opsForHash().delete(GATEWAY_ROUTE_REDIS_KEY, id);return Mono.empty();});}
}

         这样动态添加的路由信息就会被储存在redis中,而在配置文件中定义的路由信息是不会储存在redis中的:

              

 

 

 

 

  相关解决方案