本篇内容主要讲解“如何配置spring cloud 2.x版本Gateway动态路由”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何配置spring cloud 2.x版本Gateway动态路由”吧!
本文采用的Spring cloud为2.1.8RELEASE,version=Greenwich.SR3
写了几篇关于Spring Cloud Gateway的文章后发现,Gateway涉及的知识范围太广了,真是深刻体会了“一入Spring cloud深似海”。
现实生产环境中,使用Spring Cloud Gateway都是作为所有流量的入口,为了保证系统的高可用,尽量避免系统的重启,所以需要Spring Cloud Gateway的动态路由来处理。之前的文章《Gateway路由网关教程》提供的路由配置,在系统启动时候,会将路由配置和规则加载到内存当中,无法做到不重启服务就可以动态的新增、修改、删除内存中的路由配置和规则。
Spring Cloud Gateway源码中提供了GatewayControllerEndpoint类来修改路由配置,但是官方文档好像并没有做详细的使用说明,只是简单介绍了几个简单的api接口。感兴趣的小伙伴可以先查看官方文档(第11章节 Actuator API)。
引致官方文档:
The
/gateway
actuator endpoint allows to monitor and interact with a Spring Cloud Gateway application. To be remotely accessible, the endpoint has to be enabled and exposed via HTTP or JMX in the application properties.
在原来spring-gateway的基础上增加spring-boot-starter-actuator依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
management: endpoints: web: exposure: include: "*"
配置说明:management.endpoints.web.exposure.include 暴露所有的gateway端点
启动服务,访问http://localhost:8100/actuator/gateway/routes,这是我们可以看到所有的routes信息。 image-20191102225203034.png 我们也可以访问单个路由信息:http://localhost:8100/actuator/gateway/routes/CompositeDiscoveryClient_EUREKA-CLIENT
显示如下:image-20191102225853005.png
Gateway默认使用的是GatewayControllerEndpoint这个类,GatewayControllerEndpoint又继承了AbstractGatewayControllerEndpoint类。
提供的方法:(只列具了几个相关方法,其他方法小伙们可以自行查看源码)
/gateway/routes 查询所有路由信息
/gateway/routes/{id} 根据路由id查询单个信息
/gateway/routes/{id} @PostMapping 新增一个路由信息
/gateway/routes/{id} @DeleteMapping 删除一个路由信息
我们可根据/gateway/routes返回的路由信息,来模仿一个@PostMapping请求参数
{ "uri": "http://httpbin.org:80", "predicates": [ { "args": { "pattern": "/ribbon/**" }, "name": "Path" } ], "filters": [] }
这是我们可以通过postman来发送一个post请求,如图所示:
response返回1证明已经插入成功,我们可以通过http://localhost:8100/actuator/gateway/routes/查看路由信息,显示结果如下:
截图红框中的信息就是新增加的
我们可以直接用postman模拟DeleteMapping请求,http://localhost:8100/actuator/gateway/routes/addroutes
显示如下:
这时候我们在访问http://localhost:8100/actuator/gateway/routes,可以看到新增加的路由已经被删除成功了。
基于Spring Cloud Gateway默认方法实现的动态路由我就完成了,在前言中我已经提到了,这种方式是基于jvm内存实现,一旦服务重启,新增的路由配置信息就是完全消失了。所有这个时候我们可以考虑是否可以参考GatewayControllerEndpoint这类,自己实现一套动态路由方法,然后将路由信息持久化。
可以自定义实体类,我这里偷了一个懒,直接用了Gateway的RouteDefinition类,感兴趣的小伙伴可以参考RouteDefinition类自己扩展,然后写一个Convert类将自定义的类转换成RouteDefinition就可以了。
我这边采用redis做为路由配置的信息的持久层,所以写了一个RedisRouteDefinitionRepository。
package spring.cloud.demo.spring.gateway.component; import com.google.common.collect.Lists; import org.springframework.cloud.gateway.route.RouteDefinition; import org.springframework.cloud.gateway.route.RouteDefinitionRepository; import org.springframework.cloud.gateway.support.NotFoundException; import org.springframework.stereotype.Component; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import spring.cloud.demo.spring.gateway.redis.RedisUtils; import spring.cloud.demo.spring.gateway.util.JsonUtils; import javax.annotation.Resource; import java.util.List; /** * @auther: maomao * @DateT: 2019-11-03 */ @Component public class RedisRouteDefinitionRepository implements RouteDefinitionRepository { //存储的的key private final static String KEY = "gateway_dynamic_route"; @Resource private RedisUtils redisUtils; /** * 获取路由信息 * @return */ @Override public Flux<RouteDefinition> getRouteDefinitions() { List<RouteDefinition> gatewayRouteEntityList = Lists.newArrayList(); redisUtils.hgets(KEY).stream().forEach(route -> { RouteDefinition result = JsonUtils.parseJson(route.toString(), RouteDefinition.class); gatewayRouteEntityList.add(result); }); return Flux.fromIterable(gatewayRouteEntityList); } /** * 新增 * @param route * @return */ @Override public Mono<Void> save(Mono<RouteDefinition> route) { return route.flatMap(routeDefinition -> { redisUtils.hset(KEY, routeDefinition.getId(), JsonUtils.toString(routeDefinition)); return Mono.empty(); }); } /** * 删除 * @param routeId * @return */ @Override public Mono<Void> delete(Mono<String> routeId) { return routeId.flatMap(id -> { if (redisUtils.hHashKey(KEY, id)) { redisUtils.hdel(KEY, id); return Mono.empty(); } return Mono.defer(() -> Mono.error(new NotFoundException("route definition is not found, routeId:" + routeId))); }); } }
package spring.cloud.demo.spring.gateway.controller; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.gateway.route.RouteDefinition; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Mono; import spring.cloud.demo.spring.gateway.service.GatewayDynamicRouteService; import javax.annotation.Resource; /** * 自定义动态路由 * @auther: maomao * @DateT: 2019-11-03 */ @RestController @RequestMapping("/gateway") @Slf4j public class GatewayDynamicRouteController { @Resource private GatewayDynamicRouteService gatewayDynamicRouteService; @PostMapping("/add") public String create(@RequestBody RouteDefinition entity) { int result = gatewayDynamicRouteService.add(entity); return String.valueOf(result); } @PostMapping("/update") public String update(@RequestBody RouteDefinition entity) { int result = gatewayDynamicRouteService.update(entity); return String.valueOf(result); } @DeleteMapping("/delete/{id}") public Mono<ResponseEntity<Object>> delete(@PathVariable String id) { return gatewayDynamicRouteService.delete(id); } }
package spring.cloud.demo.spring.gateway.service; import org.springframework.cloud.gateway.event.RefreshRoutesEvent; import org.springframework.cloud.gateway.route.RouteDefinition; import org.springframework.cloud.gateway.support.NotFoundException; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import reactor.core.publisher.Mono; import spring.cloud.demo.spring.gateway.component.RedisRouteDefinitionRepository; import javax.annotation.Resource; /** * @auther: maomao * @DateT: 2019-11-03 */ @Service public class GatewayDynamicRouteService implements ApplicationEventPublisherAware { @Resource private RedisRouteDefinitionRepository redisRouteDefinitionRepository; private ApplicationEventPublisher applicationEventPublisher; /** * 增加路由 * @param routeDefinition * @return */ public int add(RouteDefinition routeDefinition) { redisRouteDefinitionRepository.save(Mono.just(routeDefinition)).subscribe(); applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this)); return 1; } /** * 更新 * @param routeDefinition * @return */ public int update(RouteDefinition routeDefinition) { redisRouteDefinitionRepository.delete(Mono.just(routeDefinition.getId())); redisRouteDefinitionRepository.save(Mono.just(routeDefinition)).subscribe(); applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this)); return 1; } /** * 删除 * @param id * @return */ public Mono<ResponseEntity<Object>> delete(String id) { return redisRouteDefinitionRepository.delete(Mono.just(id)).then(Mono.defer(() -> Mono.just(ResponseEntity.ok().build()))) .onErrorResume(t -> t instanceof NotFoundException, t -> Mono.just(ResponseEntity.notFound().build())); } @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; } }
application.yml配置要暴漏Gateway的所有端点,可以看考之前的配置信息。
启动Spring cloud Gateway服务,先访问http://localhost:8100/actuator/gateway/routes,查看已有的路由配置信息。然后我们用postman请求add方法,http://localhost:8100/gateway/add,如果所示:
注意截图中红框的内容。证明已经新增成功。
这时我们在访问http://localhost:8100/actuator/gateway/routes查看结果。如果所示:
同理我们可以访问update和delete方法,我这里就不过多描述了。
自定义动态路由核心原理其实就要重写网关模块,也就是之前提到的RedisRouteDefinitionRepository类。我这里偷懒没有重新定义对应的实体类,这里需要注意的是,传入参数一定要按照application.yml中配置的格式,然后转成json,如果格式不正确会报错。
gitHub地址
<center><font color=red>《Srping Cloud 2.X小白教程》目录</font></center>
spring cloud 2.x版本 Eureka Server服务注册中心教程
spring cloud 2.x版本 Eureka Client服务提供者教程
spring cloud 2.x版本 Ribbon服务发现教程(内含集成Hystrix熔断机制)
spring cloud 2.x版本 Feign服务发现教程(内含集成Hystrix熔断机制)
spring cloud 2.x版本 Zuul路由网关教程
spring cloud 2.x版本 config分布式配置中心教程
spring cloud 2.x版本 Hystrix Dashboard断路器教程
spring cloud 2.x版本 Gateway路由网关教程
spring cloud 2.x版本 Gateway自定义过滤器教程
spring cloud 2.x版本 Gateway熔断、限流教程
spring cloud 2.x版本 Gateway动态路由教程
到此,相信大家对“如何配置spring cloud 2.x版本Gateway动态路由”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。