如何使用Spring Cloud Gateway结合Nacos实现动态路由配置?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1825个文字,预计阅读时间需要8分钟。
本节开始介绍Spring Cloud Gateway中动态路由的实现方法,包括:
- Nacos集成动态路由配置- 更新配置文件即自动更新路由- MySQL+二级缓存实现- 基于Gateway的一些特性进行重写,实现路由功能
本节开始介绍 SpringCloud Gateway 中动态路由的实现方法,包括:
Nacos 集成动态路由配置,更新配置文件即自动更新路由
MySQL + 二级缓存实现,主要基于 Gateway 的一些特性进行重写,实现路由信息的自动更新
这篇文章主要介绍第一种方式:将配置文件放到 Nacos 进行托管,网关服务通过引入 Nacos 而自动更新路由配置信息。实现较为简单。
本节代码在:github.com/laolunsi/spring-boot-examples,参考例 23 即可。
下面进入正题。
1. 创建网关服务
创建一个 springboot gateway 网关服务,默认是从 yaml 文件中读取 route 的配置。如果想要从 nacos 中读取配置,就要引入nacos-config的依赖,并设置配置文件的地址。
首先创建一个空 maven 项目spring-cloud-gateway-nacos-routes,声明 springboot 和 springcloud 的版本,并引入 nacos。
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.1.RELEASE</version> <relativePath/><!--lookupparentfromrepository--> </parent> <groupId>com.eknown</groupId> <artifactId>spring-cloud-gateway-nacos-routes</artifactId> <description>SpringCloudGatewayNacos动态路由示例</description> <version>1.0-SNAPSHOT</version> <properties> <java.version>1.8</java.version> <spring-cloud.version>Hoxton.SR6</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>0.9.0.RELEASE</version> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
然后创建一个 springboot 项目,命名为:gateway-demo,引入 gateway/nacos-config 等依赖:
<parent> <groupId>com.eknown</groupId> <artifactId>spring-cloud-gateway-nacos-routes</artifactId> <version>1.0-SNAPSHOT</version> <relativePath/><!--lookupparentfromrepository--> </parent> <artifactId>gateway-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>gateway-demo</name> <description>DemoprojectforSpringBoot</description> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!--mvnrepository.com/artifact/cn.hutool/hutool-core--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-core</artifactId> <version>5.3.9</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-alibaba-nacos-config</artifactId> <version>0.9.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis-reactive</artifactId> </dependency> </dependencies>
我们知道 SpringBoot 加载配置文件的顺序是:bootstrap.yml -> application.yml 这里需要将 nacos-config 的配置项放到 bootstrap.yml 中,这样项目启动时才能优先从 nacos 中加载配置信息。主要配置如下:
server: port:8501 spring: application: name:gateway-demo cloud: nacos: discovery: server-addr:127.0.0.1:8848 config: group:${gateway.dynamicRoute.group} file-extension:json server-addr:127.0.0.1:8848 gateway: discovery: locator: enabled:true redis: host:localhost password: port:6379 database:10 #自定义的配置项,用于设置路由信息所载的配置文件,比如这里是group+dataId gateway: dynamicRoute: enabled:true dataType:nacos dataId:'yq_routes' group:'YQ_GATEWAY'
将自定义配置项加载到 Java 中:
@Configuration publicclassGatewayConfig{ publicstaticStringNACOS_DATA_ID; publicstaticStringNACOS_GROUP_ID; @Value("${gateway.dynamicRoute.dataId}") publicvoidsetNacosDataId(StringdataId){ NACOS_DATA_ID=dataId; } @Value("${gateway.dynamicRoute.group}") publicvoidsetNacosGroupId(Stringgroup){ NACOS_GROUP_ID=group; } }
下面我们重写一下 RouteDefinitionRepository 接口,将其改造成使用 Nacos 引入路由配置信息就可以了!
publicclassNacosRouteDefinitionRepositoryimplementsRouteDefinitionRepository{ privatestaticfinalLoggerlog=LoggerFactory.getLogger(NacosRouteDefinitionRepository.class); //更新路由信息需要的 privateApplicationEventPublisherpublisher; //nacos的配置信息 privateNacosConfigPropertiesnacosConfigProperties; //构造器 publicNacosRouteDefinitionRepository(ApplicationEventPublisherpublisher,NacosConfigPropertiesnacosConfigProperties){ this.publisher=publisher; this.nacosConfigProperties=nacosConfigProperties; System.out.println(GatewayConfig.NACOS_DATA_ID+","+GatewayConfig.NACOS_GROUP_ID); addListener(); } @Override publicFlux<RouteDefinition>getRouteDefinitions(){ try{ Stringcontent=nacosConfigProperties.configServiceInstance() .getConfig(GatewayConfig.NACOS_DATA_ID,GatewayConfig.NACOS_GROUP_ID,5000); List<RouteDefinition>routeDefinitions=getListByStr(content); returnFlux.fromIterable(routeDefinitions); }catch(NacosExceptione){ log.error("getRouteDefinitionsbynacoserror",e); } returnFlux.fromIterable(CollUtil.newArrayList()); } /** *添加Nacos监听 */ privatevoidaddListener(){ try{ nacosConfigProperties.configServiceInstance().addListener(GatewayConfig.NACOS_DATA_ID,GatewayConfig.NACOS_GROUP_ID,newListener(){ @Override publicExecutorgetExecutor(){ returnnull; } @Override publicvoidreceiveConfigInfo(StringconfigInfo){ log.info("自动更新配置...\r\n"+configInfo); publisher.publishEvent(newRefreshRoutesEvent(this)); } }); }catch(NacosExceptione){ log.error("nacos-addListener-error",e); } } @Override publicMono<Void>save(Mono<RouteDefinition>route){ returnnull; } @Override publicMono<Void>delete(Mono<String>routeId){ returnnull; } //从 json 中解析出路由配置信息——所以配置文件的格式一定要写对! privateList<RouteDefinition>getListByStr(Stringcontent){ if(StrUtil.isNotEmpty(content)){ returnJSONObject.parseArray(content,RouteDefinition.class); } returnnewArrayList<>(0); } }
最简单的方法是直接将这个NacosRouteDefinitionRepository类声明为 Bean。这里为了方便配置的切换写的复杂一点,通过DynamicRouteConfig来确认是否需要引入 nacos 的配置:
/** *动态路由配置 */ @Configuration @ConditionalOnProperty(prefix="gateway.dynamicRoute",name="enabled",havingValue="true") publicclassDynamicRouteConfig{ @Autowired privateApplicationEventPublisherpublisher; /** *Nacos实现方式 */ @Configuration @ConditionalOnProperty(prefix="gateway.dynamicRoute",name="dataType",havingValue="nacos",matchIfMissing=true) publicclassNacosDynRoute{ @Autowired privateNacosConfigPropertiesnacosConfigProperties; @Bean publicNacosRouteDefinitionRepositorynacosRouteDefinitionRepository(){ returnnewNacosRouteDefinitionRepository(publisher,nacosConfigProperties); } } }
到这一步我们其实已经基本完成了 gateway + nacos 动态网关的实现了。下面我们测试一下。
2. 测试
创建一个简单的 springboot web 项目,引入 nacos 作为注册中心,并实现一个接口,比如:
server: port:8502 spring: application: name:demo cloud: nacos: discovery: server-addr:127.0.0.1:8848
注:这里实际上不需要引入 nacos 作为注册中心的,因为路由实际上就是一个转发功能,这个转发操作是由 gateway 提供的,而不是 nacos 提供的。。。
接口:
@RestController @RequestMapping(value="test") publicclassTestAction{ @GetMapping(value="hello") publicStringhello(Stringname){ System.out.println("hello,"+name); return"hello,"+name; } }
启动 nacos,添加配置文件,需要设置配置文件的 group 和 dataId 与上面的gateway.dynamicRoute中的配置相同。
内容示例:
[ { "id":"demo", "uri":"lb://demo", "predicates":[ { "name":"Path", "args":{ "pattern":"/api/demo/**" } } ], "filters":[ { "name":"StripPrefix", "args":{ "parts":"2" } } ] } ]
启动 gateway-demo 以及 demo 项目,访问 gateway-demo 项目对应的路由地址,比如这里的:localhost:8501/api/demo/test/hello,如果运行正常,请求将被转发到 demo 项目的/test/hello接口,并返回对应的数据。
今天的分享就到这里啦!本来打算写一篇前文所说的第二种实现方法的文章的,不过由于二级缓存那边是用了组里封装的框架所以不便公布,后面有空我会自己实现一个基本的 demo,并同步到 Git 上!
水平有限,如有纰漏还请见谅。如果对文章内容有什么疑问,可以留言或直接联系我!thanks for your reading !
以上就是Spring Cloud Gateway + Nacos 实现动态路由的详细内容,更多关于SpringCloud Gateway 动态路由实现的资料请关注易盾网络其它相关文章!
本文共计1825个文字,预计阅读时间需要8分钟。
本节开始介绍Spring Cloud Gateway中动态路由的实现方法,包括:
- Nacos集成动态路由配置- 更新配置文件即自动更新路由- MySQL+二级缓存实现- 基于Gateway的一些特性进行重写,实现路由功能
本节开始介绍 SpringCloud Gateway 中动态路由的实现方法,包括:
Nacos 集成动态路由配置,更新配置文件即自动更新路由
MySQL + 二级缓存实现,主要基于 Gateway 的一些特性进行重写,实现路由信息的自动更新
这篇文章主要介绍第一种方式:将配置文件放到 Nacos 进行托管,网关服务通过引入 Nacos 而自动更新路由配置信息。实现较为简单。
本节代码在:github.com/laolunsi/spring-boot-examples,参考例 23 即可。
下面进入正题。
1. 创建网关服务
创建一个 springboot gateway 网关服务,默认是从 yaml 文件中读取 route 的配置。如果想要从 nacos 中读取配置,就要引入nacos-config的依赖,并设置配置文件的地址。
首先创建一个空 maven 项目spring-cloud-gateway-nacos-routes,声明 springboot 和 springcloud 的版本,并引入 nacos。
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.1.RELEASE</version> <relativePath/><!--lookupparentfromrepository--> </parent> <groupId>com.eknown</groupId> <artifactId>spring-cloud-gateway-nacos-routes</artifactId> <description>SpringCloudGatewayNacos动态路由示例</description> <version>1.0-SNAPSHOT</version> <properties> <java.version>1.8</java.version> <spring-cloud.version>Hoxton.SR6</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>0.9.0.RELEASE</version> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
然后创建一个 springboot 项目,命名为:gateway-demo,引入 gateway/nacos-config 等依赖:
<parent> <groupId>com.eknown</groupId> <artifactId>spring-cloud-gateway-nacos-routes</artifactId> <version>1.0-SNAPSHOT</version> <relativePath/><!--lookupparentfromrepository--> </parent> <artifactId>gateway-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>gateway-demo</name> <description>DemoprojectforSpringBoot</description> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!--mvnrepository.com/artifact/cn.hutool/hutool-core--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-core</artifactId> <version>5.3.9</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-alibaba-nacos-config</artifactId> <version>0.9.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis-reactive</artifactId> </dependency> </dependencies>
我们知道 SpringBoot 加载配置文件的顺序是:bootstrap.yml -> application.yml 这里需要将 nacos-config 的配置项放到 bootstrap.yml 中,这样项目启动时才能优先从 nacos 中加载配置信息。主要配置如下:
server: port:8501 spring: application: name:gateway-demo cloud: nacos: discovery: server-addr:127.0.0.1:8848 config: group:${gateway.dynamicRoute.group} file-extension:json server-addr:127.0.0.1:8848 gateway: discovery: locator: enabled:true redis: host:localhost password: port:6379 database:10 #自定义的配置项,用于设置路由信息所载的配置文件,比如这里是group+dataId gateway: dynamicRoute: enabled:true dataType:nacos dataId:'yq_routes' group:'YQ_GATEWAY'
将自定义配置项加载到 Java 中:
@Configuration publicclassGatewayConfig{ publicstaticStringNACOS_DATA_ID; publicstaticStringNACOS_GROUP_ID; @Value("${gateway.dynamicRoute.dataId}") publicvoidsetNacosDataId(StringdataId){ NACOS_DATA_ID=dataId; } @Value("${gateway.dynamicRoute.group}") publicvoidsetNacosGroupId(Stringgroup){ NACOS_GROUP_ID=group; } }
下面我们重写一下 RouteDefinitionRepository 接口,将其改造成使用 Nacos 引入路由配置信息就可以了!
publicclassNacosRouteDefinitionRepositoryimplementsRouteDefinitionRepository{ privatestaticfinalLoggerlog=LoggerFactory.getLogger(NacosRouteDefinitionRepository.class); //更新路由信息需要的 privateApplicationEventPublisherpublisher; //nacos的配置信息 privateNacosConfigPropertiesnacosConfigProperties; //构造器 publicNacosRouteDefinitionRepository(ApplicationEventPublisherpublisher,NacosConfigPropertiesnacosConfigProperties){ this.publisher=publisher; this.nacosConfigProperties=nacosConfigProperties; System.out.println(GatewayConfig.NACOS_DATA_ID+","+GatewayConfig.NACOS_GROUP_ID); addListener(); } @Override publicFlux<RouteDefinition>getRouteDefinitions(){ try{ Stringcontent=nacosConfigProperties.configServiceInstance() .getConfig(GatewayConfig.NACOS_DATA_ID,GatewayConfig.NACOS_GROUP_ID,5000); List<RouteDefinition>routeDefinitions=getListByStr(content); returnFlux.fromIterable(routeDefinitions); }catch(NacosExceptione){ log.error("getRouteDefinitionsbynacoserror",e); } returnFlux.fromIterable(CollUtil.newArrayList()); } /** *添加Nacos监听 */ privatevoidaddListener(){ try{ nacosConfigProperties.configServiceInstance().addListener(GatewayConfig.NACOS_DATA_ID,GatewayConfig.NACOS_GROUP_ID,newListener(){ @Override publicExecutorgetExecutor(){ returnnull; } @Override publicvoidreceiveConfigInfo(StringconfigInfo){ log.info("自动更新配置...\r\n"+configInfo); publisher.publishEvent(newRefreshRoutesEvent(this)); } }); }catch(NacosExceptione){ log.error("nacos-addListener-error",e); } } @Override publicMono<Void>save(Mono<RouteDefinition>route){ returnnull; } @Override publicMono<Void>delete(Mono<String>routeId){ returnnull; } //从 json 中解析出路由配置信息——所以配置文件的格式一定要写对! privateList<RouteDefinition>getListByStr(Stringcontent){ if(StrUtil.isNotEmpty(content)){ returnJSONObject.parseArray(content,RouteDefinition.class); } returnnewArrayList<>(0); } }
最简单的方法是直接将这个NacosRouteDefinitionRepository类声明为 Bean。这里为了方便配置的切换写的复杂一点,通过DynamicRouteConfig来确认是否需要引入 nacos 的配置:
/** *动态路由配置 */ @Configuration @ConditionalOnProperty(prefix="gateway.dynamicRoute",name="enabled",havingValue="true") publicclassDynamicRouteConfig{ @Autowired privateApplicationEventPublisherpublisher; /** *Nacos实现方式 */ @Configuration @ConditionalOnProperty(prefix="gateway.dynamicRoute",name="dataType",havingValue="nacos",matchIfMissing=true) publicclassNacosDynRoute{ @Autowired privateNacosConfigPropertiesnacosConfigProperties; @Bean publicNacosRouteDefinitionRepositorynacosRouteDefinitionRepository(){ returnnewNacosRouteDefinitionRepository(publisher,nacosConfigProperties); } } }
到这一步我们其实已经基本完成了 gateway + nacos 动态网关的实现了。下面我们测试一下。
2. 测试
创建一个简单的 springboot web 项目,引入 nacos 作为注册中心,并实现一个接口,比如:
server: port:8502 spring: application: name:demo cloud: nacos: discovery: server-addr:127.0.0.1:8848
注:这里实际上不需要引入 nacos 作为注册中心的,因为路由实际上就是一个转发功能,这个转发操作是由 gateway 提供的,而不是 nacos 提供的。。。
接口:
@RestController @RequestMapping(value="test") publicclassTestAction{ @GetMapping(value="hello") publicStringhello(Stringname){ System.out.println("hello,"+name); return"hello,"+name; } }
启动 nacos,添加配置文件,需要设置配置文件的 group 和 dataId 与上面的gateway.dynamicRoute中的配置相同。
内容示例:
[ { "id":"demo", "uri":"lb://demo", "predicates":[ { "name":"Path", "args":{ "pattern":"/api/demo/**" } } ], "filters":[ { "name":"StripPrefix", "args":{ "parts":"2" } } ] } ]
启动 gateway-demo 以及 demo 项目,访问 gateway-demo 项目对应的路由地址,比如这里的:localhost:8501/api/demo/test/hello,如果运行正常,请求将被转发到 demo 项目的/test/hello接口,并返回对应的数据。
今天的分享就到这里啦!本来打算写一篇前文所说的第二种实现方法的文章的,不过由于二级缓存那边是用了组里封装的框架所以不便公布,后面有空我会自己实现一个基本的 demo,并同步到 Git 上!
水平有限,如有纰漏还请见谅。如果对文章内容有什么疑问,可以留言或直接联系我!thanks for your reading !
以上就是Spring Cloud Gateway + Nacos 实现动态路由的详细内容,更多关于SpringCloud Gateway 动态路由实现的资料请关注易盾网络其它相关文章!

