前言
Nacos最近项目一直在使用,其简单灵活,支持更细粒度的命令空间,分组等为麻烦复杂的环境切换提供了方便 ;同时也很好支持动态路由的配置 ,只需要简单的几步即可。在国产的注册中心、配置中心中比较突出,容易上手,本文通过gateway、nacos-consumer、nacos-provider三个简单模块来展示:Nacos下动态路由配置。
博文中源码已上传至github(https://github.com/Jian0110/learning-cloudalibaba ),欢迎小伙伴们star
一、Nacos环境准备
1、启动Nacos配置中心并创建路由配置
具体的Nacos怎么配置就不介绍了,可以参考阿里巴巴的官方介绍,这里通过windows直接本地启动开启单机模式,登录Nacos Console,创建dev的namespace,在dev下的默认分组下创建gateway-router的dataId
gateway-router的主要初始化配置如下:关于gateway的组成(id,order、predicates断言,uri)这里就不详细说明的了,可以自行百度下
2、连接Nacos配置中心
通常在项目中配置“配置中心”往往都是在bootstrap.propertis(yaml)中配置,这样才能保证项目中路由配置从Nacos Config中读取。
Application启动类中增加注解@EnableDiscoveryClient,才能保证连接到Nacos Config
二、项目构建
1、项目结构
创建简单的spring boot多模块结构,推荐使用idea创建
1)Nacos父模块:
首先pom文件引入Spring Cloud Alibaba Nacos组件:注册中心nacos-discovery与配置中心nacos-config
其次再引入Spring Cloud相关组件依赖
其它组件依赖引入(修正:如果引入了nacos-api相关的JSON依赖,那么fastjson就不需要再引入了,否则可能冲突):
注意,这里有个坑,spring cloud gateway使用的web框架为webflux,和springMVC不兼容。所以不要引入(修正:只有gateway服务不用引入springMVC,其他需要引入)
2)三个子模块:gateway、nacos-consumer、nacos-provider
结构截图如下所示:
3)三个服务的端口分别为:
nacos-consume:6001
nacos-provider:6002
gateway:6003
4)服务架构如下:
2、编写测试代码
(1)在gateway模块中主要实现以下功能:
第一,从Nacos配置中心中加载动态路由的相关配置,就需要读取Nacos的命名空间namespace,通过dataId获取配置
properties配置关于Nacos下读取gateway-router的配置:
第二,初始化路由,监听动态路由配置的数据源变化(2020.12.28 解决删除路由不生效问题);
第三,刷新最新的动态路由变化,实现动态增删改路由(2020.12.28 解决删除路由不生效问题)
(2)在consumer创建ConsumeController: 通过访问gateway网关/consume/sayHello/{name}("pattern": "/consume/**"),跳转至nacos-consumer服务("uri": "lb://nacos-consumer"),
(3)在provider创建ProviderController :通过访问gateway网关/provide/sayHello/{name}("pattern": "/provide/**"),跳转至nacos-provider服务("uri": "lb://nacos-provider ")
三、测试动态网关配置
1、启动服务,观察注册中心
分别启动gateway、nacos-consumer、nacos-provider三个服务,观察是否已经在Nacos上正确注册
注意:需要指定注册中心的namespace为dev的空间,即spring.cloud.nacos.discovery.namespace=08ecd1e5-c042-410a-84d5-b0a8fbeed8ea
2、访问网关,观察服务日志
(1)查看gateway服务的初始化启动日志:会发现可以正常从Nacos获取配置gateway-router网关配置文件内容,并进行正确路由加载...
2020-05-10 14:33:44.557 INFO 1272 --- [ main] c.g.r.DynamicRouteServiceImplByNacos : gateway route init...
2020-05-10 14:33:44.578 INFO 1272 --- [ main] c.g.r.DynamicRouteServiceImplByNacos : 获取网关当前配置:
[{
"id": "consumer-router",
"order": 0,
"predicates": [{
"args": {
"pattern": "/consume/**"
},
"name": "Path"
}],
"uri": "lb://nacos-consumer"
},{
"id": "provider-router",
"order": 2,
"predicates": [{
"args": {
"pattern": "/provide/**"
},
"name": "Path"
}],
"uri": "lb://nacos-provider"
}]
2020-05-10 14:33:44.691 INFO 1272 --- [ main] c.g.r.DynamicRouteServiceImplByNacos : update route : RouteDefinition{id='consumer-router', predicates=[PredicateDefinition{name='Path', args={pattern=/consume/** }}], filters=[], uri=lb://nacos-consumer, order=0, metadata={}}
2020-05-10 14:33:44.691 INFO 1272 --- [ main] c.g.service.DynamicRouteServiceImpl : gateway add route RouteDefinition{id='consumer-router', predicates=[PredicateDefinition{name='Path', args={pattern=/consume/**}}], filters=[], uri=lb://nacos-consumer, order=0, metadata={}}
2020-05-10 14:33:45.192 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [After]
2020-05-10 14:33:45.192 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Before]
2020-05-10 14:33:45.192 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Between]
2020-05-10 14:33:45.193 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Cookie]
2020-05-10 14:33:45.193 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Header]
2020-05-10 14:33:45.193 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Host]
2020-05-10 14:33:45.194 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Method]
2020-05-10 14:33:45.194 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Path]
2020-05-10 14:33:45.194 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Query]
2020-05-10 14:33:45.194 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [ReadBodyPredicateFactory]
2020-05-10 14:33:45.194 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [RemoteAddr]
2020-05-10 14:33:45.194 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Weight]
2020-05-10 14:33:45.194 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [CloudFoundryRouteService]
2020-05-10 14:33:45.335 INFO 1272 --- [ main] c.g.r.DynamicRouteServiceImplByNacos : update route : RouteDefinition{id='provider-router', predicates=[PredicateDefinition{name='Path', args={pattern=/provide/**}}], filters=[], uri=lb://nacos-provider, order=2, metadata={}}
2020-05-10 14:33:45.335 INFO 1272 --- [ main] c.g.service.DynamicRouteServiceImpl : gateway add route RouteDefinition{id='provider-router', predicates=[PredicateDefinition{name='Path', args={pattern=/provide/**}}], filters=[], uri=lb://nacos-provider, order=2, metadata={}}
2020-05-10 14:33:45.336 INFO 1272 --- [ main] c.g.r.DynamicRouteServiceImplByNacos : update route : RouteDefinition{id='github-router', predicates=[PredicateDefinition{name='Path', args={pattern=/github}}], filters=[], uri= https://github.com , order=3, metadata={}}
2020-05-10 14:33:45.336 INFO 1272 --- [ main] c.g.service.DynamicRouteServiceImpl : gateway add route RouteDefinition{id='github-router', predicates=[PredicateDefinition{name='Path', args={pattern=/github}}], filters=[], uri= https://github.com , order=3, metadata={}}
View Code
但这只能说明是初始化静态路由,下面我们改变gateway-router网关配置内容,追加github-router路由
之后点击发布更新路由配置
观察gateway服务日志,有没有监听,并且进行正确的路由更新:如下日志所示,最新路由配置立马被打印,并且进行正确路由更新
2020-05-10 14:42:27.576 INFO 1272 --- [d5-b0a8fbeed8ea] c.g.r.DynamicRouteServiceImplByNacos : 进行网关更新:
[{
"id": "consumer-router",
"order": 0,
"predicates": [{
"args": {
"pattern": "/consume/**"
},
"name": "Path"
}],
"uri": "lb://nacos-consumer"
},{
"id": "provider-router",
"order": 2,
"predicates": [{
"args": {
"pattern": "/provide/**"
},
"name": "Path"
}],
"uri": "lb://nacos-provider"
},{
"id": "github-router",
"order": 2,
"predicates": [{
"args": {
"pattern": "/github/**"
},
"name": "Path"
}],
"uri": "https://github.com"
}]
2020-05-10 14:42:27.576 INFO 1272 --- [d5-b0a8fbeed8ea] c.g.r.DynamicRouteServiceImplByNacos : update route : RouteDefinition{id='consumer-router', predicates=[PredicateDefinition{name='Path', args={pattern=/consume/** }}], filters=[], uri=lb://nacos-consumer, order=0, metadata={}}
2020-05-10 14:42:27.576 INFO 1272 --- [d5-b0a8fbeed8ea] c.g.service.DynamicRouteServiceImpl : gateway update route RouteDefinition{id='consumer-router', predicates=[PredicateDefinition{name='Path', args={pattern=/consume/**}}], filters=[], uri=lb://nacos-consumer, order=0, metadata={}}
2020-05-10 14:42:27.578 INFO 1272 --- [d5-b0a8fbeed8ea] c.g.r.DynamicRouteServiceImplByNacos : update route : RouteDefinition{id='provider-router', predicates=[PredicateDefinition{name='Path', args={pattern=/provide/**}}], filters=[], uri=lb://nacos-provider, order=2, metadata={}}
2020-05-10 14:42:27.578 INFO 1272 --- [d5-b0a8fbeed8ea] c.g.service.DynamicRouteServiceImpl : gateway update route RouteDefinition{id='provider-router', predicates=[PredicateDefinition{name='Path', args={pattern=/provide/**}}], filters=[], uri=lb://nacos-provider, order=2, metadata={}}
2020-05-10 14:42:27.580 INFO 1272 --- [d5-b0a8fbeed8ea] c.g.r.DynamicRouteServiceImplByNacos : update route : RouteDefinition{id='github-router', predicates=[PredicateDefinition{name='Path', args={pattern=/github/**}}], filters=[], uri= https://github.com , order=2, metadata={}}
2020-05-10 14:42:27.580 INFO 1272 --- [d5-b0a8fbeed8ea] c.g.service.DynamicRouteServiceImpl : gateway update route RouteDefinition{id='github-router', predicates=[PredicateDefinition{name='Path', args={pattern=/github/**}}], filters=[], uri= https://github.com , order=2, metadata={}}
View Code
其实,还有办法可以知道我们的gateway服务有没有监听Nacos的gateway-router配置,那就是在Nacos Console--->监听查询----->选择配置---->输入配置文件的namespace与Group: 可以发现我本地IP地址127.0.0.1对配置文件gateway-router进行了监听
(2)访问gateway网关服务:http://localhost:6003/consume/sayHello/nacos
查看consumer服务日志:
发现跳转至consumer服务,并且访问了consumer服务的CosnumerController
(3)访问gateway网关服务:http://localhost:6003/provider/sayHello/nacos
查看provider服务日志:
发现跳转至consumer服务,并且访问了provider服务的ProviderController
(4)访问访问gateway网关服务:http://localhost:6003/ github,正确跳转至github页面
四、总结
1)Spring Cloud Gateway作用不光只是简单的跳转重定向,还可以实现用户的验证登录,解决跨域,日志拦截,权限控制,限流,熔断,负载均衡,黑名单和白名单机制等。是微服务架构不二的选择 ;
2)Nacos的配置中心支持动态获取配置文件,可以将一些全局的经常变更的配置文件放在Nacos下 ,需要到微服务自行获取。
---------------------------------Change log--------------------------------
2020.12.28 解决删除路由不生效问题,主要是利用RouteDefinitionLocator先读取变化之前的RouteDefinition,之后删除重新再更新,或者可以实现routeDefinitionWriter、RouteDefinitionLocator重写如下方法:
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix