Nacos config提供了配置中心的解决方案,且功能非常的强大适用,提供单机与集群模式
- 系统集成的方式
- maven包依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>0.2.1.RELEASE</version>
</dependency>
2.bootstrap.properties配置文件
#nacos配置中心地址
spring.cloud.nacos.config.server-addr=10.136.15.122:8848
#默认应用名称,配置中心中data-id 默认为name+file-extension
spring.application.name=example
没有配置情况下用name作为前缀
#spring.cloud.nacos.config.prefix
#应用文件格式支持properties,yml两种
spring.cloud.nacos.config.file-extension=properties
3.java应用代码
package com.nacos;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/config")
@RefreshScope
public class ConfigController {
@Value("${useLocalCache:false}")
private boolean useLocalCache;
/**
* http://localhost:8080/config/get
*/
@RequestMapping("/get")
public boolean get() {
return useLocalCache;
}
}
package com.nacos;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class NacosConfigApplication {
public static void main(String[] args) {
SpringApplication.run(NacosConfigApplication.class, args);
}
}
4.启动应用,nacos配置中心配置参数,访问/config/get 结果为true ,结果配置成功
- 参数配置说明
#配置中心地址
spring.cloud.nacos.config.server-addr=10.136.15.122:8848
#应用名称,非必须,如果没有配置prefix,默认以name为前缀
#spring.application.name=example
#data-id前缀
spring.cloud.nacos.config.prefix=example
#文件类型,支持properties和yml两种数据格式
spring.cloud.nacos.config.file-extension=properties
#环境,可以隔离不同配置环境之间的配置,如dev,uat,pro
spring.profiles.active=dev
#命名空间 也是起隔离作用的,隔离不同应用这之间的作用
spring.cloud.nacos.config.namespace=c04b0cdf-91c7-470a-b6a9-423da6cc7a2b
#分组起隔离同一命名空间下,不同的分组
spring.cloud.nacos.config.group=test
#加载额外配置,除加载上面主配置文件外,额外加载的公有配置功能
spring.cloud.nacos.config.ext-config[0].data-id=test.properties
spring.cloud.nacos.config.ext-config[0].refresh=true
- 部分源码解析
NacosPropertySourceLocator类是Nacos Config的核心执行类,实现了PropertySourceLocator接口,在SpringCloud项目启动中就会加载执行的类,具体如下
PropertySourceBootstrapConfiguration 是SpringCloud下的配置类实现了ApplicationContextInitializer接口,执行init方法,具本原因可以查询ApplicationContextInitializer相关接口的文档说明,代码如下
public void initialize(ConfigurableApplicationContext applicationContext) {
CompositePropertySource composite = new CompositePropertySource(
BOOTSTRAP_PROPERTY_SOURCE_NAME);
AnnotationAwareOrderComparator.sort(this.propertySourceLocators);
boolean empty = true;
ConfigurableEnvironment environment = applicationContext.getEnvironment();
for (PropertySourceLocator locator : this.propertySourceLocators) {
PropertySource<?> source = null;
source = locator.locate(environment);
if (source == null) {
continue;
}
logger.info("Located property source: " + source);
composite.addPropertySource(source);
empty = false;
}
if (!empty) {
MutablePropertySources propertySources = environment.getPropertySources();
String logConfig = environment.resolvePlaceholders("${logging.config:}");
LogFile logFile = LogFile.get(environment);
if (propertySources.contains(BOOTSTRAP_PROPERTY_SOURCE_NAME)) {
propertySources.remove(BOOTSTRAP_PROPERTY_SOURCE_NAME);
}
insertPropertySources(propertySources, composite);
reinitializeLoggingSystem(environment, logConfig, logFile);
setLogLevels(applicationContext, environment);
handleIncludedProfiles(environment);
}
}
发现最终执行的locate方法,我们查看下NacosPropertySourceLocator的locate的实现如下
public PropertySource<?> locate(Environment env) {
ConfigService configService = nacosConfigProperties.configServiceInstance();
if (null == configService) {
LOGGER.warn(
"no instance of config service found, can't load config from nacos");
return null;
}
long timeout = nacosConfigProperties.getTimeout();
nacosPropertySourceBuilder = new NacosPropertySourceBuilder(configService,
timeout);
String name = nacosConfigProperties.getName();
/*配置的分组*/
String nacosGroup = nacosConfigProperties.getGroup();
/*配置的前缀*/
String dataIdPrefix = nacosConfigProperties.getPrefix();
if (StringUtils.isEmpty(dataIdPrefix)) {
dataIdPrefix = name;
}
/*前缀没有,则取spring.application.name*/
if (StringUtils.isEmpty(dataIdPrefix)) {
dataIdPrefix = env.getProperty("spring.application.name");
}
List<String> profiles = Arrays.asList(env.getActiveProfiles());
nacosConfigProperties.setActiveProfiles(profiles.toArray(new String[0]));
String fileExtension = nacosConfigProperties.getFileExtension();
CompositePropertySource composite = new CompositePropertySource(
NACOS_PROPERTY_SOURCE_NAME);
loadSharedConfiguration(composite);
loadExtConfiguration(composite);
/*加载配置方法*/
loadApplicationConfiguration(composite, nacosGroup, dataIdPrefix, fileExtension);
return composite;
}
通过这个方法,大概能明白我们上面的一些配置的作用,下面再看下loadApplicationConfiguration 加载配置的方法,loadSharedConfiguration,loadExtConfiguration是加载扩展配置的方式,这里就详细说明了
private void loadApplicationConfiguration(
CompositePropertySource compositePropertySource, String nacosGroup,
String dataIdPrefix, String fileExtension) {
loadNacosDataIfPresent(compositePropertySource,
dataIdPrefix + DOT + fileExtension, nacosGroup, fileExtension, true);
for (String profile : nacosConfigProperties.getActiveProfiles()) {
String dataId = dataIdPrefix + SEP1 + profile + DOT + fileExtension;
loadNacosDataIfPresent(compositePropertySource, dataId, nacosGroup,
fileExtension, true);
}
}
这里可以看到,会优先加载dateIdPrefix+DOT+fileExtension的配置,而后在加载环境的配置从而覆盖之前的配置,这就是上面配置dev的作用
private void loadNacosDataIfPresent(final CompositePropertySource composite,
final String dataId, final String group, String fileExtension,
boolean isRefreshable) {
if (NacosContextRefresher.loadCount.get() != 0) {
NacosPropertySource ps;
if (!isRefreshable) {
ps = NacosPropertySourceRepository.getNacosPropertySource(dataId);
}
else {
ps = nacosPropertySourceBuilder.build(dataId, group, fileExtension, true);
}
composite.addFirstPropertySource(ps);
}
else {
NacosPropertySource ps = nacosPropertySourceBuilder.build(dataId, group,
fileExtension, isRefreshable);
composite.addFirstPropertySource(ps);
}
}
再往下就是拉取配置中心的数据的过程,就不看下去了