基于Nacos实现Spring Cloud Gateway实现动态路由的方法
简介
该文档主要介绍以Nacos为配置中心,实现Spring Cloud GateWay 实现动态路由的功能。Spring Cloud Gateway启动时候,就将路由配置和规则加载到内存里,无法做到不重启网关就可以动态的对应路由的配置和规则进行增加,修改和删除。通过nacos的配置下发的功能可以实现在不重启网关的情况下,实现动态路由。
集成
Spring Cloud GateWay集成
spring-cloud-starter-gateway:路由转发、请求过滤(权限校验、限流以及监控等)
spring-boot-starter-webflux:反应式Web框架
spring-boot-starter-actuator:监控系统健康
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
Nacos集成
nacos-client:nacos客户端,现在用比较新的版本0.9.0
<dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> <version>0.9.0</version> </dependency>
动态路由
DynamicRouteServiceImpl:提供动态路由的基础方法,可通过获取bean操作该类的方法。该类提供新增路由、更新路由、删除路由,然后实现发布的功能。
@Service public class DynamicRouteServiceImpl implements ApplicationEventPublisherAware { @Autowired private RouteDefinitionWriter routeDefinitionWriter; private ApplicationEventPublisher publisher; /** * 增加路由 * @param definition * @return */ public String add(RouteDefinition definition) { routeDefinitionWriter.save(Mono.just(definition)).subscribe(); this.publisher.publishEvent(new RefreshRoutesEvent(this)); return "success"; } /** * 更新路由 * @param definition * @return */ public String update(RouteDefinition definition) { try { this.routeDefinitionWriter.delete(Mono.just(definition.getId())); } catch (Exception e) { return "update fail,not find route routeId: "+definition.getId(); } try { routeDefinitionWriter.save(Mono.just(definition)).subscribe(); this.publisher.publishEvent(new RefreshRoutesEvent(this)); return "success"; } catch (Exception e) { return "update route fail"; } } /** * 删除路由 * @param id * @return */ public String delete(String id) { try { this.routeDefinitionWriter.delete(Mono.just(id)); return "delete success"; } catch (Exception e) { e.printStackTrace(); return "delete fail"; } } @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.publisher = applicationEventPublisher; } }
RouteDefinition: 提供路由实体类,主要有predicates匹配来自用户的请求,filters服务路由
@Validated public class RouteDefinition { @NotEmpty private String id = UUID.randomUUID().toString(); @NotEmpty @Valid private List<PredicateDefinition> predicates = new ArrayList<>(); @Valid private List<FilterDefinition> filters = new ArrayList<>(); @NotNull private URI uri; private int order = 0; public RouteDefinition() {} public RouteDefinition(String text) { int eqIdx = text.indexOf("="); if (eqIdx <= 0) { throw new ValidationException("Unable to parse RouteDefinition text '" + text + "'" + ", must be of the form name=value"); } setId(text.substring(0, eqIdx)); String[] args = tokenizeToStringArray(text.substring(eqIdx+1), ","); setUri(URI.create(args[0])); for (int i=1; i < args.length; i++) { this.predicates.add(new PredicateDefinition(args[i])); } } public String getId() { return id; } public void setId(String id) { this.id = id; } public List<PredicateDefinition> getPredicates() { return predicates; } public void setPredicates(List<PredicateDefinition> predicates) { this.predicates = predicates; } public List<FilterDefinition> getFilters() { return filters; } public void setFilters(List<FilterDefinition> filters) { this.filters = filters; } public URI getUri() { return uri; } public void setUri(URI uri) { this.uri = uri; } public int getOrder() { return order; } public void setOrder(int order) { this.order = order; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; RouteDefinition routeDefinition = (RouteDefinition) o; return Objects.equals(id, routeDefinition.id) && Objects.equals(predicates, routeDefinition.predicates) && Objects.equals(order, routeDefinition.order) && Objects.equals(uri, routeDefinition.uri); } @Override public int hashCode() { return Objects.hash(id, predicates, uri); } @Override public String toString() { return "RouteDefinition{" + "id='" + id + '\'' + ", predicates=" + predicates + ", filters=" + filters + ", uri=" + uri + ", order=" + order + '}'; } }
NacosGatewayProperties:自定义属性绑定值,可通过配置文件配置属性。
@ConfigurationProperties(prefix="nacos", ignoreUnknownFields = true) @Configuration public class NacosGatewayProperties { private String address; private String dataId; private String groupId; private Long timeout; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getDataId() { return dataId; } public void setDataId(String dataId) { this.dataId = dataId; } public String getGroupId() { return groupId; } public void setGroupId(String groupId) { this.groupId = groupId; } public Long getTimeout() { return timeout; } public void setTimeout(Long timeout) { this.timeout = timeout; } }
DynamicRouteServiceImplByNacos: 实现runner,通过nacos下发动态路由配置
@Component public class DynamicRouteServiceImplByNacos implements CommandLineRunner{ @Autowired private DynamicRouteServiceImpl dynamicRouteService; @Autowired private NacosGatewayProperties nacosGatewayProperties; /** * 监听Nacos Server下发的动态路由配置 * @param dataId * @param group */ public void dynamicRouteByNacosListener (){ try { ConfigService configService=NacosFactory.createConfigService(nacosGatewayProperties.getAddress()); String content = configService.getConfig(nacosGatewayProperties.getDataId(), nacosGatewayProperties.getGroupId(), nacosGatewayProperties.getTimeout()); System.out.println(content); configService.addListener(nacosGatewayProperties.getDataId(), nacosGatewayProperties.getGroupId(), new Listener() { @Override public void receiveConfigInfo(String configInfo) { List<RouteDefinition> list = JsonUtils.toList(configInfo, RouteDefinition.class); list.forEach(definition->{ dynamicRouteService.update(definition); }); } @Override public Executor getExecutor() { return null; } }); } catch (NacosException e) { e.printStackTrace(); } } @Override public void run(String... args) throws Exception { dynamicRouteByNacosListener(); } }
nacos配置下发
nacos配置
nacos: address: 127.0.0.1:8848 data-id: dhap-gateway # group-id: AAA timeout: 5000
nacos属性文件定义
新建dataID为
groupID为AAA
[ { "filters": [], "id": "blog1", "order": 0, "predicates": [{ "args": { "pattern": "/z" }, "name": "Path" }], "uri": "https://blog.csdn.net/zhangchangbin123" }, { "filters": [], "id": "blog1", "order": 0, "predicates": [{ "args": { "pattern": "/c" }, "name": "Path" }], "uri": "https://blog.csdn.net/zhangchangbin123" } ]
查看路由信息
到此这篇关于基于Nacos实现Spring Cloud Gateway实现动态路由的方法的文章就介绍到这了,更多相关Spring Cloud Gateway动态路由内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!
相关文章
基于springcloud异步线程池、高并发请求feign的解决方案
这篇文章主要介绍了基于springcloud异步线程池、高并发请求feign的解决方案,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-02-25- 这篇文章主要介绍了Spring AOP 对象内部方法间的嵌套调用方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-08-29
Spring Cloud 中@FeignClient注解中的contextId属性详解
这篇文章主要介绍了Spring Cloud 中@FeignClient注解中的contextId属性详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-09-25Springboot如何实现Web系统License授权认证
这篇文章主要介绍了Springboot如何实现Web系统License授权认证,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-05-28完美解决SpringCloud-OpenFeign使用okhttp替换不生效问题
这篇文章主要介绍了完美解决SpringCloud-OpenFeign使用okhttp替换不生效问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-02-25如何在Spring WebFlux的任何地方获取Request对象
这篇文章主要介绍了如何在Spring WebFlux的任何地方获取Request对象,帮助大家更好的理解和使用springboot框架,感兴趣的朋友可以了解下...2021-01-26- 这篇文章主要介绍了详解SpringCloudGateway内存泄漏问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-07-16
- @Autowired 注解的主要功能就是完成自动注入,使用也非常简单,但这篇文章主要给大家介绍了关于Spring为什么不推荐使用@Autowired注解的相关资料,需要的朋友可以参考下...2021-11-03
Springboot如何使用mybatis实现拦截SQL分页
这篇文章主要介绍了Springboot使用mybatis实现拦截SQL分页,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-06-19如何解决springcloud feign 首次调用100%失败的问题
这篇文章主要介绍了如何解决springcloud feign 首次调用100%失败的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-06-23- 这篇文章主要介绍了SpringMVC文件上传原理及实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-07-15
解决php导致nginx报502 bad gateway错误问题
502 bad gateway这个问题很多朋友一看就以为是nginx或apache的问题,其实不然了,除了它们两会出现这个问题之外还有像php模块也会导致此问题的出现了,下面一起来看看吧....2016-11-25Spring Data JPA 关键字Exists的用法说明
这篇文章主要介绍了Spring Data JPA 关键字Exists的用法说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-06-10- 这篇文章主要介绍了spring cloud gateway中如何读取请求参数的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-07-15
tomcat启动完成执行 某个方法 定时任务(Spring)操作
这篇文章主要介绍了tomcat启动完成执行 某个方法 定时任务(Spring)操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-09-25使用Maven 搭建 Spring MVC 本地部署Tomcat的详细教程
这篇文章主要介绍了使用Maven 搭建 Spring MVC 本地部署Tomcat,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-08-16- 502 bad gateway是php-fpm的问题对于这个问题就是配置参数的问题了,下面我们整理了一些关于php-fpm错误问题的解决办法,具体如下。 今天升级完PHP出现了502 Bad Gat...2016-11-25
- 这篇文章主要介绍了springboot中nacos动态路由的配置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-09-11
- 这篇文章主要介绍了Spring Cloud负载均衡及远程调用实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2021-09-18
- 这篇文章主要介绍了SpringMvc自动装箱及GET请求参数原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-09-19