在传统的单体应用中,配置信息通常直接写在项目的配置文件里,比如application.yml或者application.properties。这种方式在小型项目中没什么问题,但随着业务规模扩大,特别是转向微服务架构后,问题就逐渐暴露出来了。
想象一下,一个电商系统有几十个微服务,每个服务都有自己的配置。如果某个参数需要调整,比如订单服务的超时时间从30秒改为60秒,开发人员需要:
这个过程不仅耗时费力,而且服务重启期间还会影响用户体验。更糟的是,如果多个服务共用同一个配置,修改起来简直就是噩梦。
Nacos配置中心就是为了解决这些问题而生的。它把配置集中管理,提供实时推送能力,让配置修改可以立即生效,完全不需要重启服务。我在实际项目中就遇到过这样的场景:大促期间需要临时调整库存阈值,如果走传统方式,等所有服务重启完,促销可能都结束了。而用了Nacos后,改完配置点个发布,所有服务瞬间就生效了。
Nacos的安装非常简单,我这里推荐使用Docker方式,一行命令就能搞定:
bash复制docker run --name nacos-standalone -e MODE=standalone -p 8848:8848 -d nacos/nacos-server:latest
如果不用Docker,也可以直接下载压缩包。目前最新稳定版是2.2.3,下载后解压运行:
bash复制# Linux/Mac
sh startup.sh -m standalone
# Windows
startup.cmd -m standalone
启动成功后,访问http://localhost:8848/nacos,默认账号密码都是nacos。第一次看到控制台可能会觉得有点复杂,但其实我们主要用配置管理这个功能。
虽然standalone模式开箱即用,但生产环境还是建议调整几个关键参数:
properties复制# 数据持久化配置(默认使用内嵌数据库,生产建议改用MySQL)
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8
db.user=root
db.password=yourpassword
# 集群节点配置(单机模式不需要)
nacos.inetutils.ip-address=你的服务器IP
我刚开始用的时候没注意持久化配置,结果服务器重启后所有配置都丢了,这个坑大家一定要避开。
以订单服务为例,首先在pom.xml中添加必要依赖:
xml复制<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2022.0.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.1.4</version>
</dependency>
注意SpringCloud Alibaba的版本要和SpringBoot版本对应,我整理了个常用版本对照表:
| SpringBoot | SpringCloud | SpringCloud Alibaba |
|---|---|---|
| 2.6.x | 2021.0.x | 2021.0.4.0 |
| 2.7.x | 2022.0.x | 2022.0.0.0 |
| 3.0.x | 2023.0.x | 2023.0.0.0 |
在resources目录下创建bootstrap.yml(注意不是application.yml):
yaml复制spring:
application:
name: order-service
profiles:
active: dev
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
namespace: dev
group: DEFAULT_GROUP
file-extension: yaml
refresh-enabled: true
discovery:
server-addr: 127.0.0.1:8848
这里有几个容易踩坑的点:
在订单服务中,我们创建一个配置类来管理业务参数:
java复制@RefreshScope
@Configuration
public class OrderConfig {
@Value("${order.timeout:30}")
private Integer timeout;
@Value("${stock.threshold:10}")
private Integer stockThreshold;
// getters...
}
然后在Nacos控制台创建Data ID为order-service-dev.yaml的配置,内容如下:
yaml复制order:
timeout: 30
stock:
threshold: 10
启动服务后,我们测试下热更新效果:
我实测下来,更新几乎是实时的,延迟通常在1秒以内。不过要注意,@RefreshScope会重新创建Bean实例,所以如果是频繁更新的配置,最好配合@ConfigurationProperties使用。
实际项目会有dev、test、prod等多个环境,Nacos提供了三种隔离方式:
我的经验是:小型项目用Data ID区分环境就够了,中大型项目建议使用namespace。
Nacos会自动保存配置的修改历史,在控制台点击"历史版本"就能看到所有变更记录。如果发现配置有问题,可以快速回滚到之前的版本。这个功能在线上出问题时特别有用,我有次半夜改错配置,就是靠历史版本功能紧急恢复的。
有时候我们需要在配置变更时执行一些自定义逻辑,可以这样实现:
java复制@Autowired
private ConfigurableApplicationContext context;
@EventListener
public void refreshConfig(RefreshScopeRefreshedEvent event) {
// 配置刷新后执行的逻辑
log.info("配置已更新,新timeout值:{}", orderConfig.getTimeout());
}
Nacos提供了metrics接口,可以集成Prometheus监控:
我在项目中遇到过配置推送失败的情况,后来通过监控及时发现是网络问题。建议至少对推送失败和读取异常设置告警。
问题1:配置更新不生效
问题2:启动时报配置找不到
问题3:配置更新导致性能下降
记得第一次用Nacos时,我因为没加@RefreshScope调试了半天。后来养成了习惯,所有配置类都加上这个注解,省去不少麻烦。