Nacos配置中心之加载配置

简介: Nacos配置中心之加载配置

Nacos配置中心之加载配置

启动类执行完prepareEnvironment后,执行prepareContext进行刷新应用上下文件的准备

public ConfigurableApplicationContext run(String... args) {
   StopWatch stopWatch = new StopWatch();
   stopWatch.start();
   ConfigurableApplicationContext context = null;
   Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
   configureHeadlessProperty();
   SpringApplicationRunListeners listeners = getRunListeners(args);
   listeners.starting();
   try {
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(
            args);
       //环境准备
      ConfigurableEnvironment environment = prepareEnvironment(listeners,
            applicationArguments);
      configureIgnoreBeanInfo(environment);
      Banner printedBanner = printBanner(environment);
      context = createApplicationContext();
      exceptionReporters = getSpringFactoriesInstances(
            SpringBootExceptionReporter.class,
            new Class[] { ConfigurableApplicationContext.class }, context);
      prepareContext(context, environment, listeners, applicationArguments,
            printedBanner);
      refreshContext(context);
      afterRefresh(context, applicationArguments);
      stopWatch.stop();
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass)
               .logStarted(getApplicationLog(), stopWatch);
      }
      listeners.started(context);
      callRunners(context, applicationArguments);
   }
   catch (Throwable ex) {
      handleRunFailure(context, ex, exceptionReporters, listeners);
      throw new IllegalStateException(ex);
   }

   try {
      listeners.running(context);
   }
   catch (Throwable ex) {
      handleRunFailure(context, ex, exceptionReporters, null);
      throw new IllegalStateException(ex);
   }
   return context;
}

prepareContext方法:

private void prepareContext(ConfigurableApplicationContext context,
      ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
      ApplicationArguments applicationArguments, Banner printedBanner) {
   context.setEnvironment(environment);
   postProcessApplicationContext(context);
   applyInitializers(context);
   listeners.contextPrepared(context);
   if (this.logStartupInfo) {
      logStartupInfo(context.getParent() == null);
      logStartupProfileInfo(context);
   }
   // Add boot specific singleton beans
   ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
   beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
   if (printedBanner != null) {
      beanFactory.registerSingleton("springBootBanner", printedBanner);
   }
   if (beanFactory instanceof DefaultListableBeanFactory) {
      ((DefaultListableBeanFactory) beanFactory)
            .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
   }
   // Load the sources
   Set<Object> sources = getAllSources();
   Assert.notEmpty(sources, "Sources must not be empty");
   load(context, sources.toArray(new Object[0]));
   listeners.contextLoaded(context);
}

调用applyInitializers

@SuppressWarnings({ "rawtypes", "unchecked" })
protected void applyInitializers(ConfigurableApplicationContext context) {
   for (ApplicationContextInitializer initializer : getInitializers()) {
      Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(
            initializer.getClass(), ApplicationContextInitializer.class);
      Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
      initializer.initialize(context);
   }
}

PropertySourceBootstrapConfiguration实现了ApplicationContextInitializer接口,所欲会调用PropertySourceBootstrapConfiguration的initialize方法,

@Override
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);
   }
}

locator.locate(environment)调用NacosPropertySourceLocator的locate方法

@Override
public PropertySource<?> locate(Environment env) {

   ConfigService configService = nacosConfigProperties.configServiceInstance();

   if (null == configService) {
      log.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 dataIdPrefix = nacosConfigProperties.getPrefix();
   if (StringUtils.isEmpty(dataIdPrefix)) {
      dataIdPrefix = name;
   }

   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;
}
  1. 初始化ConfigService对象,ConfigService是Nacos客户端提供的用于访问实现配置中心基本操作的类
  2. 按照顺序分别加载共享配置、扩展配置、应用名称对应的配置。

进入loadApplicationConfiguration-》loadNacosDataIfPresent-》loadNacosPropertySource-》build-》loadNacosData

private Properties loadNacosData(String dataId, String group, String fileExtension) {
   String data = null;
   try {
      data = configService.getConfig(dataId, group, timeout);
      if (StringUtils.isEmpty(data)) {
         log.warn(
               "Ignore the empty nacos configuration and get it based on dataId[{}] & group[{}]",
               dataId, group);
         return EMPTY_PROPERTIES;
      }
      log.info(String.format(
            "Loading nacos data, dataId: '%s', group: '%s', data: %s", dataId,
            group, data));

      Properties properties = NacosDataParserHandler.getInstance()
            .parseNacosData(data, fileExtension);
      return properties == null ? EMPTY_PROPERTIES : properties;
   }
   catch (NacosException e) {
      log.error("get data from Nacos error,dataId:{}, ", dataId, e);
   }
   catch (Exception e) {
      log.error("parse data from Nacos error,dataId:{},data:{},", dataId, data, e);
   }
   return EMPTY_PROPERTIES;
}

configService.getConfig方法从Nacos配置中心上加载配置进行填充

总结:
启动类执行完prepareEnvironment后,执行prepareContext进行刷新应用上下文件的准备,调用applyInitializers,调用NacosPropertySourceLocator的locate方法,初始化ConfigService对象,按照顺序分别加载共享配置、扩展配置、应用名称对应的配置,进入loadNacosData方法,然后configService.getConfig方法从Nacos配置中心上加载配置进行填充。

这就是nacos初始化的大体流程,如果我们在工作中遇到获取nacos数据获取不到的时候,我们可以试着跟踪一下nacos加载数据的流程,分析问题,定位问题,及时解决。

相关文章
|
1月前
|
Dubbo 关系型数据库 MySQL
nacos常见问题之命名空间配置数据上线修改如何解决
Nacos是阿里云开源的服务发现和配置管理平台,用于构建动态微服务应用架构;本汇总针对Nacos在实际应用中用户常遇到的问题进行了归纳和解答,旨在帮助开发者和运维人员高效解决使用Nacos时的各类疑难杂症。
92 1
|
1月前
|
存储 运维 监控
NACOS 配置中心和注册中心是分两个集群部署还是放在一个集群中
【2月更文挑战第33天】NACOS 配置中心和注册中心是分两个集群部署还是放在一个集群中
76 2
|
17天前
|
SpringCloudAlibaba Java Nacos
SpringCloud Alibaba微服务 -- Nacos使用以及注册中心和配置中心的应用(保姆级)
SpringCloud Alibaba微服务 -- Nacos使用以及注册中心和配置中心的应用(保姆级)
|
1月前
|
编解码 Java Nacos
nacos常见问题之密码加密配置如何解决
Nacos是阿里云开源的服务发现和配置管理平台,用于构建动态微服务应用架构;本汇总针对Nacos在实际应用中用户常遇到的问题进行了归纳和解答,旨在帮助开发者和运维人员高效解决使用Nacos时的各类疑难杂症。
139 0
|
1月前
|
安全 前端开发 Nacos
nacos常见问题之配置注册的白名单如何解决
Nacos是阿里云开源的服务发现和配置管理平台,用于构建动态微服务应用架构;本汇总针对Nacos在实际应用中用户常遇到的问题进行了归纳和解答,旨在帮助开发者和运维人员高效解决使用Nacos时的各类疑难杂症。
93 0
|
1月前
|
网络安全 Nacos 数据安全/隐私保护
nacos常见问题之配置内容不显示也修改不了如何解决
Nacos是阿里云开源的服务发现和配置管理平台,用于构建动态微服务应用架构;本汇总针对Nacos在实际应用中用户常遇到的问题进行了归纳和解答,旨在帮助开发者和运维人员高效解决使用Nacos时的各类疑难杂症。
104 0
|
1月前
|
运维 Java Nacos
nacos常见问题之配置不生效不加载shared-configs 配置如何解决
Nacos是阿里云开源的服务发现和配置管理平台,用于构建动态微服务应用架构;本汇总针对Nacos在实际应用中用户常遇到的问题进行了归纳和解答,旨在帮助开发者和运维人员高效解决使用Nacos时的各类疑难杂症。
98 0
|
1月前
|
SpringCloudAlibaba Dubbo 前端开发
【三】SpringCloud Alibaba之Nacos整合篇(作为配置中心)
【三】SpringCloud Alibaba之Nacos整合篇(作为配置中心)
233 0
|
1月前
|
运维 Java Nacos
nacos常见问题之配置账号密码
Nacos是阿里云开源的服务发现和配置管理平台,用于构建动态微服务应用架构;本汇总针对Nacos在实际应用中用户常遇到的问题进行了归纳和解答,旨在帮助开发者和运维人员高效解决使用Nacos时的各类疑难杂症。
247 6
|
2月前
|
安全 Linux Nacos
解决“nacos默认secret.key配置不当权限绕过漏洞“
解决“nacos默认secret.key配置不当权限绕过漏洞“
155 0