springcloud使用nacos作为配置中心

配置

maven配置

<!--version 2022.0.4-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>
<!--version 3.0.9-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<!--version 2022.0.0-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

yaml配置

spring:
  application:
    name: nacos-demo
  cloud:
    nacos:
      server-addr: localhost:8848
  config:
    import:
    ## nacos-config是nacos里配置文件的dataId,和以前的配置有所区别,不需要加上文件后缀
    ## 可以配置多个文件,相同的配置项,后面的会覆盖前面的
      - nacos:nacos-config

由于springboot已经在2.4.0版本默认关闭了bootstrap.yaml功能,改用spring.config.import来配置要加载的各种来源的配置文件。旧项目升级版本时,可以通过引入spring-cloud-starter-bootstrap依赖,或者设定环境变量spring.cloud.bootstrap.enabled=true,来继续使用bootstrap.yaml

获取nacos配置原理

启动时加载nacos配置

我们知道在springboot启动的时候,在容器刷新前,会从各个数据源里获取到配置信息,常见的有系统环境变量,application.yaml,web项目还有servletConfig和servletContext。显然nacos里的配置信息也会在这里注入进去。核心逻辑在SpringApplication#prepareEnvironment()

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
			DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
		// Create and configure the environment
		ConfigurableEnvironment environment = getOrCreateEnvironment();
		configureEnvironment(environment, applicationArguments.getSourceArgs());
		ConfigurationPropertySources.attach(environment);
		listeners.environmentPrepared(bootstrapContext, environment);
		// 省略部分非关键代码
		return environment;
	}

通过debug watch environment对象的propertySources属性,发现在listeners.environmentPrepared方法执行后,获取到了nacos里的配置信息。这句代码实际就是在创建environment对象,并添加了几个本地配置源后,广播了环境准备就绪的事件。显然核心逻辑在监听了environmentPrepared事件的监听器里。environmentPrepared事件属于springboot 6个生命周期事件之一,由SpringApplicationRunlistener的实现类来监听,nacos的NacosLoggingAppRunListener实现了该接口。但是点进去发现该监听器并没有对environment做任何的修改。

public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
    NacosLogging.getInstance().loadConfiguration();
}

逻辑只能在另一个SpringApplicationRunlistener的实现类EventPublishingRunListener里,该类将生命周期事件进行了一次广播,广播给了ApplicationListener的实现类.

public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,
		ConfigurableEnvironment environment) {
	multicastInitialEvent(
			new ApplicationEnvironmentPreparedEvent(bootstrapContext, this.application, this.args, environment));
}

通过debug发现,在ApplicationListener的实现类EnvironmentPostProcessorApplicationListener进行时间处理后,获取到了参数值,该类则是遍历执行了EnvironmentPostProcessor。
发现其中有一个后置处理器COnfigDataEnvironmentPostProcessor,该类完成了从本地配置文件application.yaml以及从spring.config.import配置里获取的其他数据源配置文件的配置读取。
在这里插入图片描述
其中从nacos远程获取配置文件配置的逻辑由NacosConfigDataLoader完成,它从上下文里获取到了nacos配置项,然后调用了pullConfig方法来请求nacos里的配置。最终的实际请求由ClientWorker类进行

public ConfigData doLoad(ConfigDataLoaderContext context, NacosConfigDataResource resource) {
    try {
        ConfigService configService = ((NacosConfigManager)this.getBean(context, NacosConfigManager.class)).getConfigService();
        NacosConfigProperties properties = (NacosConfigProperties)this.getBean(context, NacosConfigProperties.class);
        NacosConfigDataResource.NacosItemConfig config = resource.getConfig();
        List<PropertySource<?>> propertySources = this.pullConfig(configService, config.getGroup(), config.getDataId(), config.getSuffix(), (long)properties.getTimeout());
        NacosPropertySource propertySource = new NacosPropertySource(propertySources, config.getGroup(), config.getDataId(), new Date(), config.isRefreshEnabled());
        NacosPropertySourceRepository.collectNacosPropertySource(propertySource);
        return new ConfigData(propertySources, this.getOptions(context, resource));
    } catch (Exception var8) {
        this.log.error("Error getting properties from nacos: " + resource, var8);
        if (!resource.isOptional()) {
            throw new ConfigDataResourceNotFoundException(resource, var8);
        } else {
            return null;
        }
    }
}

因此,最终的事件通知链是:

  1. 发布environmentPrepared事件
  2. EventPublishingRunListener广播事件给EnvironmentPostProcessorApplicationListener
  3. EnvironmentPostProcessorApplicationListener遍历EnvironmentPostProcessor后置处理器进行后置处理
  4. 后置处理器ConfigDataEnvironmentPostProcessor创建了很多ConfigDataEnvironmentContributor,对于spring.config.import、spring.config.additional-locatio和spring.config.location配置项,会标记为INITIAL_IMPORT状态并添加ConfigDataProperties参数(ConfigDataEnvironment()->createContributors()->getInitialImportContributors()->addInitialImportContributors()->ConfigDataEnvironmentContributor.ofInitialImport()),之后使用ConfigDataLocationResolvers利用参数进行解析,然后调用加载器进行加载(ConfigDataEnvironmentContributors#withProcessedImports->ConfigDataImporter#resolveAndLoad())。
    整个处理链里,大部分都是spring定义好的固定流程,需要我们自定义的是解析器和加载器,nacos实现的解析器是NacosConfigDataLocationResolver,实现的加载器NacosConfigDataLoader,两个类都是通过spring.factories文件注入的
  • 26
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值