Spring Cloud Alibaba Nacos Config进阶使用
作者:gblfy
一、SpringBoot 使用 Nacos Config 实现多环境切换
1. 现象
在日常开发过程中,对于同一个服务或者项目工程在不同的环境所需要的配置是不同的。如访问数据库、redis或者MQ其他中间件,往往需要进行环境隔离,如果每次部署都需要去修改配置文件的话,是十分不方面的。在微服务场景下,这个问题尤为突出,因为代码工程的数量是传统单项目的几十倍。需要建筑一些组件,在不修改配置稳健的前提下动态的切换运行环境。Nacos Config提供了类似的解决方案。
2. 引入依赖
在pom文件中添加Nacos Config的依赖包,注意版本
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.2.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--服务注册发现--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <!--spring-cloud-alibaba 版本控制--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.2.6.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
3. 添加bootstrap.yaml配置文件
spring: cloud: nacos: server-addr: localhost:8848 # nacos服务地址 config: file-extension: yaml # 表示支持扩展的文件名 application: name: nacos-config # 表示当前微服务需要向配置中心索要nacos-config的配置 profiles: active: prod # 表示我需要向配置中心索要生产环境的配置
4. 配置对应关系图
在Nacos Config 配置管理中新增配置如图以及其对应关系如下:
5. 文件格式简述
索要文件的格式为${application.name}-spring。profiles.active.{file-extension}
体现在nacos中,对应尚曼的格式Data id得知应该是nacos-config-prod.yaml
6. 启动nacos
官网:
https://nacos.io/zh-cn/docs/quick-start.html
# 启动命令(standalone代表着单机模式运行,非集群模式): # linux sh startup.sh -m standalone # Windows startup.cmd -m standalone
http://localhost:8848/nacos/
账号/密码:nacos/nacos
7. 添加生产配置
标签 | 值 | 说明 |
---|---|---|
Data ID | nacos-config-prod.yaml | |
Group | DEFAULT_GROUP | 默认,可以自定义 |
描述 | 简述生产环境配置 | |
配置格式 | yaml | 文件扩展名选择 |
配置内容 | nacosProd: Production environment configuration | 和配置yml文件格式语法一样 |
8. 添加测试controller
package com.gblfy.alibab.nacosconfig.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RefreshScope public class NacosConfigController { @Value("${nacosProd}") private String nacosProd; @GetMapping("/nacosProd") public String getNacosProd() { return nacosProd; } }
9. 启动Springboot工程并观察到如下日志则为成功
10. 浏览器验证
打开浏览器访问http://localhost:8080/nacosProd验证测试结果结果如图:
11. 调整激活环境
修改bootstrap.yaml文件中激活环境调整为test环境spring.profiles.active.test
spring: cloud: nacos: server-addr: localhost:8848 # nacos服务地址 config: file-extension: yaml # 表示支持扩展的文件名 application: name: nacos-config # 表示当前微服务需要向配置中心索要nacos-config的配置 profiles: active: test # 表示我需要向配置中心索要生产环境的配置
12. 新建test环境配置
在nacos中新建data_id为nacos-config-test.yaml,并添加相同的配置参数,把环境参数的内容调整为test测试环境的
13. test配置关系图
14. 测试方法
添加test测试环境方法,把刚才生产的方法注释掉,因为咱们现在激活的是test测试环境的配置
// @Value("${nacosProd}") // private String nacosProd; // // @GetMapping("/nacosProd") // public String getNacosProd() { // return nacosProd; // } @Value("${nacosTest}") private String nacosTest; @GetMapping("/nacosTest") public String getNacosTest() { return nacosTest; }
15. 重启springboot服务,监控控制台输出
16. 浏览器验证
打开浏览器访问http://localhost:8080/nacosTest验证测试结果结果如图:
17. 配置修改实时生效
在修改nacos中修改配置实时生效测试
修改前配置:
修改后配置:
发布规则
不停止项目服务,打开浏览器访问http://localhost:8080/nacosTest验证测试结果结果如图:
其他环境同上这里就不一一验证了。
18. 不同环境配置动态切换如何实现?
这里演示修改配置文件,到正式环境,激活那个环境配置是在命令脚本中配置好的
会采用下面这种方式激活环境配置,这个命令配置环境的优先级比项目中的配置文件中的优先级高
java -jar xxx.jar -Dspring.profiles.active=test
二、如何解决不同环境相同配置的问题
2.1. 现象
在实际的开发过程中,我们的工程项目所用到的配置参数大多数并不需要根据不同的环境进行区分,生产、测试、开发环境所用到的参数值是相同的。如何解决同一服务在多环境中,引用相同配置的问题呢?Nacos Config也提供了相应的解决方案。
2.2. 添加配置
在Nacos Config中添加配置,data_id为nacos-config.yaml,如图所示:
2.3. 增加测试方法
在NacosConfigController类中添加读取项目中共有相同配置的方法进行测试
// @Value("${nacosProd}") // private String nacosProd; // // @GetMapping("/nacosProd") // public String getNacosProd() { // return nacosProd; // } @Value("${nacosTest}") private String nacosTest; @GetMapping("/nacosTest") public String getNacosTest() { return nacosTest; } @Value("${nacosCommon}") private String nacosCommon; @GetMapping("/nacosCommon") public String getNacosCommon() { return nacosCommon; }
2.4. 重新启动项目,观察控制台
2.5. 浏览器验证
打开浏览器访问http://localhost:8080/nacosTest验证测试结果结果如图:
打开浏览器访问http://localhost:8080/nacosCommon验证测试结果结果如图:
从上面测试可以看出,访问test环境独有的配置可以正常访问。访问项目中共有相同的配置也正常。
此时,我们已经在nacos中配置了3个配置文件,nacos-config-prod.yaml、nacos-config-test.yaml和nacos-config.yaml
三、如果同一个配置项在三个配置文件中都存在且值不同,最终项目读取是哪个呢?
3.1. 验证思路
验证这个其实很简单,只需要在环境独有的配置中配置共有相同配置文件中相同的配置标签让他值不一样,浏览器访问不就知道了,对吧?
这样,演示在nacos-config-test.yaml
文件中配置nacos-config.yaml文件中nacosCommon标签,给他赋予不同的值进行测试。
3.2. 添加相同配置
nacos-config.yaml文件中原配置:
在nacos-config-test.yaml
文件中配置nacosCommon标签值为
添加相同配置
在测试配置中添加与公用配置一样的标签属性值不同,观察谁的配置生效即可
nacosTest: Test environment configuration v2 nacosCommon: Common Environment Configuration 测试配置文件中,配置相同属性值不同的测试案例
规则发布
3.3. 浏览器验证
打开浏览器访问http://localhost:8080/nacosCommon验证测试结果结果如图:
实际读取的配置信息是从nacos-config-test.yaml
文件中读取的。
结论:如果配置了spring.profiles.active,则优先获取nacos-config-{spring.profiles.active}.yaml中的值。
四、不同微服务之间相同配置如何共享
4.1. 解决方案简述
像这种共有中间件的配置信息企业会采用单独的配置文件来维护,Nacos Config为我们提供了二种配置方式来解决此类场景的问题,分别是extension-configs和shard-configs配置方式。
4.2. 通过shard-configs配置方式
在nacos中新建redis.yaml,添加配置信息,reidsip:127.0.0.1,然后,配置信息发布生效
修改项目的bootstrap.yaml的配置文件,添加配置spring.cloud.nacos.config.shared-configs[0]
spring: cloud: nacos: server-addr: localhost:8848 # nacos服务地址 config: file-extension: yaml # 表示支持扩展的文件名 shared-configs[0]: data_id: redis.yaml refresh: true # 默认是false 如果需要支持自动刷新,需要配置true,搭配@RefreshScope实现动态刷新 #group: # 可以不写 默认DEFAULT_GROUP application: name: nacos-config # 表示当前微服务需要向配置中心索要nacos-config的配置 profiles: active: test # 表示我需要向配置中心索要生产环境的配置
添加测试方法
@Value("${redisip}") private String redisip; @GetMapping("/redisip") public String getredisip() { return redisip; }
打开浏览器访问http://localhost:8080/redisip验证测试结果结果如图:
http://localhost:8080/redisip
4.3. 如何添加多个shared-configs配置呢?
在nacos中新建mq.yaml,添加配置信息mqip: 127.0.0.2
修改项目的bootstrap.yaml问阿金,并添加shared-configs[1]:配置,具体配置线如下:
spring: cloud: nacos: server-addr: localhost:8848 # nacos服务地址 config: file-extension: yaml # 表示支持扩展的文件名 shared-configs[0]: data_id: redis.yaml refresh: true # 默认是false 如果需要支持自动刷新,需要配置true,搭配@RefreshScope实现动态刷新 #group: # 可以不写 默认DEFAULT_GROUP shared-configs[1]: data_id: mq.yaml refresh: true # 默认是false 如果需要支持自动刷新,需要配置true,搭配@RefreshScope实现动态刷新 #group: # 可以不写 默认DEFAULT_GROUP application: name: nacos-config # 表示当前微服务需要向配置中心索要nacos-config的配置 profiles: active: test # 表示我需要向配置中心索要生产环境的配置
新增一个获取mq信息的url以及方法
package com.gblfy.alibab.nacosconfig.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RefreshScope public class NacosConfigController { // @Value("${nacosProd}") // private String nacosProd; // // @GetMapping("/nacosProd") // public String getNacosProd() { // return nacosProd; // } @Value("${nacosTest}") private String nacosTest; @GetMapping("/nacosTest") public String getNacosTest() { return nacosTest; } @Value("${nacosCommon}") private String nacosCommon; @GetMapping("/nacosCommon") public String getNacosCommon() { return nacosCommon; } @Value("${redisip}") private String redisip; @GetMapping("/redisip") public String getredisip() { return redisip; } @Value("${mqip}") private String mqip; @GetMapping("/mqip") public String getmqip() { return mqip; } }
打开浏览器访问http://localhost:8080/mqip验证测试结果结果如图:
4.4. 通过extension-configs方式
修改bootstrap.yaml文件,删除shared-configs相关配置,增加extension-configs[0]和extension-configs[1]的配置如下:
spring: cloud: nacos: server-addr: localhost:8848 # nacos服务地址 config: file-extension: yaml # 表示支持扩展的文件名 extension-configs[0]: # shared-configs是一个列表 List<Config> sharedConfigs data_id: redis.yaml refresh: true # 默认是false 如果需要支持自动刷新,需要配置true,搭配@RefreshScope实现动态刷新 extension-configs[1]: # shared-configs是一个列表 List<Config> sharedConfigs data_id: mq.yaml refresh: true # 默认是false 如果需要支持自动刷新,需要配置true,搭配@RefreshScope实现动态刷新 #group: # 可以不写 默认DEFAULT_GROUP application: name: nacos-config # 表示当前微服务需要向配置中心索要nacos-config的配置 profiles: active: test # 表示我需要向配置中心索要生产环境的配置
重新启动项目,分别访问http://localhost:8080/redisip和http://localhost:8080/mqip验证是否可以正常读取redis.yaml和mq.yaml的配置信息
4.5. 配置实时刷新测试验证
在nacos中修改redis.yaml和mq.yaml的信息,不重启项目,直接访问浏览器,验证配置是否生效
redis.yaml原配置:
mq.yaml修改后配置:
mq.yaml原配置:
mq.yaml修改后配置:
访问http://localhost:8080/redisip和http://localhost:8080/mqip验证
五、多个shard-configs的文件中存在相同的配置
5.1. 思考1
如果多个shard-configs的文件中存在相同的配置,最终会以那个配置文件中的值为准?
5.2. 分析验证思路
这样场景
例如:在redis.yaml和mq.yaml配置文件中有一个相同的配置属性但是值不一样,然后在项目中存在多个shard-configs的文件,到底优先获取谁的配置问价心中的信息呢?对吧
5.3. 验证流程
- 1.在nacos上在redis.yaml和mq.yaml配置文件中都配置一个属性为port的属性,redis.yaml文件中配置6379,和mq.yaml配置文件中port配置5672
- 2.在项目中的bootstrap.yaml中配置多个shard-configs
- 3.在测试类中添加测试方法
- 4.浏览器验证
- 5.得出结论
5.4. 流程实战
- 1.在nacos上在redis.yaml和mq.yaml配置文件中都配置一个属性为port的属性,redis.yaml文件中配置6379,和mq.yaml配置文件中port配置5672
- 2.在项目中的bootstrap.yaml中配置多个shard-configs
spring: cloud: nacos: server-addr: localhost:8848 # nacos服务地址 config: file-extension: yaml # 表示支持扩展的文件名 extension-configs[0]: # shared-configs是一个列表 List<Config> sharedConfigs data_id: redis.yaml refresh: true # 默认是false 如果需要支持自动刷新,需要配置true,搭配@RefreshScope实现动态刷新 extension-configs[1]: # shared-configs是一个列表 List<Config> sharedConfigs data_id: mq.yaml refresh: true # 默认是false 如果需要支持自动刷新,需要配置true,搭配@RefreshScope实现动态刷新 #group: # 可以不写 默认DEFAULT_GROUP application: name: nacos-config # 表示当前微服务需要向配置中心索要nacos-config的配置 profiles: active: test # 表示我需要向配置中心索要生产环境的配置
- 3.在测试类中添加测试方法
@GetMapping("/port") public String getport() { return port; }
- 4.浏览器验证
- 5.得出结论
结论:会以数组最后一个配置文件内容为准
六、配置文件优先级
6.1. springboot
提示springboot配置文件优先级
(bootstrap.ptoterties > bootstrap.yaml > application.ptoterties > bootstrap.yaml)
6.2. nacos
如果同时在extension-configs和shard-configs存在相同的配置,最终会以那个文件中的值为准?
总结下configdemo.yaml、configdemo-test.yaml、和shard-configs、extension-configs读取优先级
extension-configs: - data-id: shareconfig3.yml group: share3_group refresh: true - data-id: shareconfig3.yml group: share4_group refresh: true shared-configs: - data-id: shareconfig1.yml refresh: true - data-id: shareconfig2.yml refresh: true
spring.cloud.nacos.config.extension-configs[n].data-id 其中 n 的值越大,优先级越高,因此会走group=share4_group的配置。
spring.cloud.nacos.config.shared-configs[n].data-id默认跟上面一样的逻辑。
不同方式配置加载优先级
Spring Cloud Alibaba Nacos Config 目前提供了三种配置能力从 Nacos 拉取相关的配置。
A: 通过 spring.cloud.nacos.config.shared-configs[n].data-id 支持多个共享 Data Id 的配置
B: 通过 spring.cloud.nacos.config.extension-configs[n].data-id 的方式支持多个扩展 Data Id 的配置
C: 通过内部相关规则(spring.cloud.nacos.config.prefix、spring.cloud.nacos.config.file-extension、spring.cloud.nacos.config.group)自动生成相关的 Data Id 配置
当三种方式共同使用时,他们的一个优先级关系是:A < B < C