写在前面
源码 。
本文看下如下集成nacos config组件。
1:常见配置方式分析
我们先来看下常见的配置方式都有哪些,以及其有什么优点和缺点。
- 硬编码
优点:
hardcode,除了开发的时候快些,爽一下,有个屁优点
缺点:
配置和业务耦合,无法做到职责分离
灵活度低
修改配置需要修改代码,并重启应用,无法做到运行期灵活变更,对业务影响大,开发人员工作量大
- 本地配置文件
优点:
配置和业务解耦
缺点:
灵活度低
无法做到运行期零或变更,修改配置需要重启程序
当修改文件较多时,开发人员修改配置文件工作量大,且容易出错
- -D环境变量
优点:
配置和业务解耦
优点:
灵活度低
无法做到运行期灵活变更,修改配置需要重启应用
安全性低,容易泄露密码等敏感信息
当应用较多时,修改的成本比较高,且容易出错
无法进行版本维护,无法快读回滚到某历史版本
- 数据库
优点:
配置和业务解耦
缺点:
灵活度低
无法进行版本维护,无法快读回滚到某历史版本
高并发场景下,可能将数据库打崩,因此需要时刻关注数据库的性能指标
以上传统配置方式存在的问题,配置中心可解,配置中心方式分析如下:
缺点:
需要引入额外的组件,增加运维成本
优点:
灵活度高
通过动态变更的推送可实现运行期动态修改,某些场景下无需重启
安全性高,通过权限控制提高安全性
版本管理,实现快速回滚到历史版本
统一管理配置文件,修改成本低
可参考下面几张图:
2:基于nacos config配置实战
我们以改造custom模块为例来作为实战内容,看下配置项动态更新,首先在custom模块引入依赖:
<!-- 添加Nacos Config配置项 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 读取bootstrap文件 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
创建bootstrap.yml(springboot中该配置文件加载优先级最高,保证最先加载)
配置配置中心相关信息,如下:
spring:
# 必须把name属性从application.yml迁移过来,否则无法动态刷新
application:
name: coupon-customer-serv-config
cloud:
nacos:
config:
# nacos config服务器的地址
server-addr: 192.168.10.99:8868
file-extension: yml
# prefix: 文件名前缀,默认是spring.application.name
# 如果没有指定命令空间,则默认命令空间为PUBLIC
namespace: dev
# 如果没有配置Group,则默认值为DEFAULT_GROUP
group: DEFAULT_GROUP
# 从Nacos读取配置项的超时时间
timeout: 5000
# 长轮询超时时间
config-long-poll-timeout: 10000
# 轮询的重试时间
config-retry-time: 2000
# 长轮询最大重试次数
max-retry: 3
# 开启监听和自动刷新
refresh-enabled: true
# Nacos的扩展配置项,数字越大优先级越高
extension-configs:
- dataId: redis-config.yml
group: EXT_GROUP
# 动态刷新
refresh: true
- dataId: rabbitmq-config.yml
group: EXT_GROUP
refresh: true
extension-configs
中是设置其他的配置文件,如配置各种三方组件连接信息的配置文件,这里是redis-config.yml和rabbitmq-config.yml。然后,我们点击页面右上角的➕符号创建三个配置文件,coupon-customer-serv.yml(默认分组)、redis-config.yml(EXT_GROUP 分组)和 rabbitmq-config.yml(EXT_GROUP 分组),创建后如下图:
其中coupon-customer-serv-config配置文件内容如下:
# 是否发放优惠券的业务开关
disableCouponRequest: false
spring:
# application:
# name: coupon-customer-serv
datasource:
# mysql数据源
username: root
password: root
url: jdbc:mysql://192.168.10.114:3316/geekbang_coupon_db?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
# 连接池
hikari:
pool-name: GeekbangCouponHikari
connection-timeout: 5000
idle-timeout: 30000
maximum-pool-size: 10
minimum-idle: 5
max-lifetime: 60000
auto-commit: true
注意这里配置了spring.datasource信息,因此需要将application.yml中的注释掉。disableCouponRequest: false
我们来使用其来测试配置动态更新功能。接着在CouponCustomerContrller中注入该属性(防止没有,给默认值false)
:
@Value("${disableCouponRequest:false}")
private Boolean disableCoupon;
修改dongshi.daddy.config.controller.CouponCustomerController#requestCoupon
,为如下,增加是否发放优惠券的控制:
@PostMapping("requestCoupon")
public Coupon requestCoupon(@Valid @RequestBody RequestCoupon request) {
if (disableCoupon) {
System.out.println("暂停优惠券发放");
return null;
} else {
System.out.println("优惠券正常发放");
}
return customerService.requestCoupon(request);
}
最后需要在在CouponCustomerContrller中添加注解@RefreshScope
开启配置动态更新,最后就可以启动服务了:
...
2024-01-04 15:52:48.643 INFO 21232 --- [ main] c.a.n.client.config.impl.ClientWorker : [fixed-192.168.10.99_8868-dev] [subscribe] coupon-customer-serv-config+DEFAULT_GROUP+dev
2024-01-04 15:52:48.643 INFO 21232 --- [ main] c.a.nacos.client.config.impl.CacheData : [fixed-192.168.10.99_8868-dev] [add-listener] ok, tenant=dev, dataId=coupon-customer-serv-config, group=DEFAULT_GROUP, cnt=1
2024-01-04 15:52:48.644 INFO 21232 --- [ main] c.a.n.client.config.impl.ClientWorker : [fixed-192.168.10.99_8868-dev] [subscribe] coupon-customer-serv-config.yml+DEFAULT_GROUP+dev
2024-01-04 15:52:48.644 INFO 21232 --- [ main] c.a.nacos.client.config.impl.CacheData : [fixed-192.168.10.99_8868-dev] [add-listener] ok, tenant=dev, dataId=coupon-customer-serv-config.yml, group=DEFAULT_GROUP, cnt=1
看到以上信息则为成功了,接着我们来测试:
http://localhost:20001/coupon-customer/requestCoupon
{
"userId": 1,
"couponTemplateId": 2
}
接着通过如下操作修改disableCouponRequest为false:
接着查看后台日志输出:
2024-01-04 16:01:27.737 INFO 21632 --- [.10.99_8868-dev] c.a.n.client.config.impl.ClientWorker : [fixed-192.168.10.99_8868-dev] [data-received] dataId=coupon-customer-serv-config, group=DEFAULT_GROUP, tenant=dev, md5=2c03eb542c19f0231dea5abe524540e5, content=# 是否发放优惠券的业务开关
disableCouponRequest: false
spring:
# application:
# name: coupon-customer-serv
..., type=yaml
看其中的[data-received]
就说明是配置动态更新通知,接着再来请求接口:
http://localhost:20001/coupon-customer/requestCoupon
{
"userId": 1,
"couponTemplateId": 2
}