Nacos的自动刷新和多环境管理
☞ 博客导航,带你有序的阅读和学习!
文章目录
自动刷新
所谓自动刷新,通俗说就是指当我们在Nacos配置中心管理界面修改之后,相应服务会自动读取到修改后的配置。
自动刷新的功能是默认开启的,测试如下:
修改主程序
@SpringBootApplication
public class NacosConfigSimpleApplication {
public static void main(String[] args) throws InterruptedException {
ConfigurableApplicationContext applicationContext =
SpringApplication.run(NacosConfigSimpleApplication.class, args);
//取到Spring的配置环境
while(true){
ConfigurableEnvironment environment = applicationContext.getEnvironment();
String username = environment.getProperty("user.name");
String age = environment.getProperty("user.age");
System.out.println("username:"+username+" | age:"+age);
TimeUnit.SECONDS.sleep(1);
}
}
}
测试结果
然后我们修改相应的配置文件的age字段的数据,可以看到Idea的控制输出信息:
关闭自动刷新
spring.cloud.nacos.config.refresh.enabled = false
# 关闭动态刷新
可以通过上述配置来关闭配置自动刷新。
我们可以看看源码:[默认为true]。
@Component
public class NacosRefreshProperties {
@Value("${spring.cloud.nacos.config.refresh.enabled:true}")
private boolean enabled = true;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
Nacos的配置类:NacosConfigProperties
@ConfigurationProperties(NacosConfigProperties.PREFIX)
public class NacosConfigProperties {
public static final String PREFIX = "spring.cloud.nacos.config";
private String serverAddr;
private String encode;
private String group = "DEFAULT_GROUP";
private String prefix;
private String fileExtension = "properties";
private int timeout = 3000;
private String endpoint;
private String namespace;
private String accessKey;
private String secretKey;
private String contextPath;
private String clusterName;
private String name;
private String sharedDataids;
private String refreshableDataids;
private List<Config> extConfig;
private ConfigService configService;
//getter & setter
public static class Config {
private String dataId;
private String group = "DEFAULT_GROUP";
private boolean refresh = false;
//getter & setter
}
//toString
public ConfigService configServiceInstance() {...}
}
NacosConfig 自动配置:NacosConfigAutoConfiguration
@Configuration
@ConditionalOnProperty(name = "spring.cloud.nacos.config.enabled", matchIfMissing = true)
public class NacosConfigAutoConfiguration {}
//即如果没有在配置文件中配置spring.cloud.nacos.config.enabled,则默认为条件满足。所以不配置,我们依旧启用了配置功能。
多环境profile管理
profile粒度控制
首先我们在Nocos控制页面配置两个不同环境的配置,如下:
nacos-config-develop.yaml:
current.env: develop-env
nacos-config-product.yaml:
current.env: product-env
修改主程序,增加读取环境类型的属性:
public static void main(String[] args) throws InterruptedException {
ConfigurableApplicationContext applicationContext = SpringApplication.run(NacosConfigSimpleApplication.class, args);
//取到Spring的配置环境
// while(true){
ConfigurableEnvironment environment = applicationContext.getEnvironment();
String username = environment.getProperty("user.name");
String age = environment.getProperty("user.age");
String env = environment.getProperty("current.env");
System.out.println("username:"+username+" | age:"+age +" | env:"+env);
TimeUnit.SECONDS.sleep(1);
// }
}
然后在配置bootstrap.properties配置文件指定激活环境:
几种激活方式可以查看:https://blog.csdn.net/ooyhao/article/details/100939089#Profile_176
spring.application.name=nacos-config
# 配置文件的格式
spring.cloud.nacos.config.file-extension=yaml
# 禁用配置自动刷新功能
#spring.cloud.nacos.config.refresh.enabled = false
# 配置中心的地址:端口
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
# 激活环境 *
spring.profiles.active=develop
注意:${spring.profiles.active}当通过配置文件来指定的时候,必须放在bootstrap.properties文件中。
通过结果可以看出,读取到的配置有nacos-config.yaml和nacos-config-develop.yaml。
注意:此示例中我们通过spring.profile.active= <profilename>
的方式写死在配置文件中,而在真正的项目实施过程中,这个变量的值需要不同环境而有不同的值。这个时候通常的做法是通过 -Dspring.profiles.active=<profile>
参数指定其配置来达到环境间灵活的切换。 具体可以参考上述链接内容
总结:文件匹配规则如下(dataId),${spring.cloud.nacos.config.prefix}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
我们可以看看源码:
加载配置源码分析
NacosConfigProperties类
@ConfigurationProperties(NacosConfigProperties.PREFIX)
public class NacosConfigProperties {
public static final String PREFIX = "spring.cloud.nacos.config";
private String serverAddr;
private String encode;
private String group = "DEFAULT_GROUP";
private String prefix;
private String fileExtension = "properties";
private int timeout = 3000;
private String endpoint;
private String namespace;
private String accessKey;
private String secretKey;
private String contextPath;
private String clusterName;
private String name;
private String sharedDataids;
private String refreshableDataids;
}
上述删除了部分代码,但是我们可以看到,fileExtension的默认值是properties.所以,在前一节中,我们使用properties格式的配置文件时,是没有配置文件扩展类型的。
注意:上面的配置类中有prefix,并且按上述的文件匹配规则来看,我们应该加载不到nacos-config.yaml
文件的,但是测试结果是加载到了这个文件,而我们并没有配置前缀,所以可以推断出,模式是使用spring.application
属性。 我们查看源码可以看到原因:
NacosPropertySourceLocator类:我们粗略的看一下(源码恐怖,后续深入研究)
@Order(0)
public class NacosPropertySourceLocator implements PropertySourceLocator {
private static final String NACOS_PROPERTY_SOURCE_NAME = "NACOS";
private static final String SEP1 = "-";
private static final String DOT = ".";
private static final String SHARED_CONFIG_SEPARATOR_CHAR = "[,]";
//配置文件类型
private static final List<String> SUPPORT_FILE_EXTENSION =
Arrays.asList("properties","yaml", "yml");
@Override
public PropertySource<?> locate(Environment env) {
//删除了部分无关内容
//spring.cloud.nacos.config.name
String name = nacosConfigProperties.getName();
//spring.cloud.nacos.config.prefix
String dataIdPrefix = nacosConfigProperties.getPrefix();
//如果没有配置prefix,则使用name属性作为prefix
if (StringUtils.isEmpty(dataIdPrefix)) {
dataIdPrefix = name;
}
//如果没有配置prefix,并且也没有配置name属性,则使用spring.application.name属性
//作为prefix的值
if (StringUtils.isEmpty(dataIdPrefix)) {
dataIdPrefix = env.getProperty("spring.application.name");
}
CompositePropertySource composite = new CompositePropertySource(
NACOS_PROPERTY_SOURCE_NAME);
loadSharedConfiguration(composite);
loadExtConfiguration(composite);
//我们再看一下这个方法,如下
loadApplicationConfiguration(composite, dataIdPrefix,
nacosConfigProperties, env);
return composite;
}
private void loadApplicationConfiguration(
CompositePropertySource compositePropertySource, String dataIdPrefix,
NacosConfigProperties properties, Environment environment) {
//spring.cloud.nacos.config.prefix
String fileExtension = properties.getFileExtension();
//spring.cloud.nacos.config.group 默认DEFAULT_GROUP
String nacosGroup = properties.getGroup();
//dataId=${prefix}-${profile}.${file-extension}
// 上面的例子中的nacos-config.yaml
loadNacosDataIfPresent(compositePropertySource,
dataIdPrefix + DOT + fileExtension, nacosGroup, fileExtension,
true);
//加载激活了的profile的配置文件
// 上例中的nacos-config-develop.yaml
for (String profile : environment.getActiveProfiles()) {
String dataId = dataIdPrefix + SEP1 + profile + DOT + fileExtension;
loadNacosDataIfPresent(compositePropertySource, dataId, nacosGroup,
fileExtension, true);
}
}
}
注意:通过上述代码分析,就知道为什么加载了nacos-config.yaml
和 nacos-config-develop.yaml
.
多环境Group管理
在没有自定义${spring.cloud.nacos.config.group}
配置的情况下,默认使用的是DEFAULT_GROUP
, 如果需要自定义,可以通过下面的配置来实现:
spring.cloud.nacos.config.group=DEVELOP_GROUP
注意:该配置必须放在bootstrap.properties文件中,并且在添加配置时的值一定要和spring.cloud.nacos.config.group
的属性值一致。
默认配置
Develop配置
测试结果
//: Loading nacos data, dataId: 'nacos-config.yaml', group: 'DEVELOP_GROUP'
//: Loading nacos data, dataId: 'nacos-config-develop.yaml', group: 'DEVELOP_GROUP'
username:欧阳 | age:23 | env:DEV
多环境namespace管理
概述
我们看一下官方时如何介绍namespace的:
用户进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的Group或Data ID的配置。Namespace的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。
在配置文件中没有自定义namespace的时候,模式使用的是Nacos上Public作为namespace,如果我们希望自定义,可以通过${spring.cloud.nacos.config.namespace}
来配置。
默认命名空间
我们先看之前的默认namespace。
自定义命名空间
spring.cloud.nacos.config.namespace= dc7fb953-fab6-4f98-95b9-e777d02cd683
注意:这个配置必须放在bootstrap.properties文件中。并且spring.cloud.nacos.config.namespace
配置的是namespace Id。而不是命名空间名称。并且这个命名空间id是不用自己生成的,只要在Nacos新建一个命名空间,管理页面就会自动产生一个字符串。在配置文件中配置时要注意选择相应的namespace,否则会读不到正确的配置。
这里为了保证配置的干净,我新建一个项目来测试。
完整配置
# DataId
spring.application.name=nacos-config-namespace
# group
spring.cloud.nacos.config.group=ouYangGroup
# namespace
spring.cloud.nacos.config.namespace=dc7fb953-fab6-4f98-95b9-e777d02cd683
spring.cloud.nacos.config.file-extension=yaml
spring.cloud.nacos.config.server-addr=192.168.1.104:8848
Nacos配置
测试结果
主程序:
@SpringBootApplication
public class NacosConfigNamespaceApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext
= SpringApplication.run(NacosConfigNamespaceApplication.class, args);
//环境
ConfigurableEnvironment environment = applicationContext.getEnvironment();
String username = environment.getProperty("user.username");
String password = environment.getProperty("user.password");
System.out.println("username:"+username+" | password:"+password);
}
}
测试结果:
username:admin | password:123456