springboot 通过Apollo-client加载配置的过程

1.Apollo-client利用springboot的META-INF/spring.factories将ApolloApplicationContextInitializer添加到springboot的ApplicationContextInitializer

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.ctrip.framework.apollo.spring.boot.ApolloAutoConfiguration
org.springframework.context.ApplicationContextInitializer=\
com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer

2.springboot启动时.经过前面的资源收集.然后加载ApplicationContextInitializer.即执行ApolloApplicationContextInitializer.java中initialize().此类为apollo入口类

@Overridepublic void initialize(ConfigurableApplicationContext context) {ConfigurableEnvironment environment = context.getEnvironment();initializeSystemProperty(environment);String enabled = environment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_ENABLED, "false");if (!Boolean.valueOf(enabled)) {logger.debug("Apollo bootstrap config is not enabled for context {}, see property: ${{}}", context, PropertySourcesConstants.APOLLO_BOOTSTRAP_ENABLED);return;}logger.debug("Apollo bootstrap config is enabled for context {}", context);if (environment.getPropertySources().contains(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME)) {//already initializedreturn;}String namespaces = environment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_NAMESPACES, ConfigConsts.NAMESPACE_APPLICATION);logger.debug("Apollo bootstrap namespaces: {}", namespaces);List<String> namespaceList = NAMESPACE_SPLITTER.splitToList(namespaces);CompositePropertySource composite = new CompositePropertySource(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME);for (String namespace : namespaceList) {Config config = ConfigService.getConfig(namespace);composite.addPropertySource(configPropertySourceFactory.getConfigPropertySource(namespace, config));}environment.getPropertySources().addFirst(composite);}

3.方法中进入Config config = ConfigService.getConfig(namespace);

4.ConfigService.java

public static Config getConfig(String namespace) {return s_instance.getManager().getConfig(namespace);
}

5.进入DefaultConfigManager

@Override
public Config getConfig(String namespace) {Config config = m_configs.get(namespace);if (config == null) {synchronized (this) {config = m_configs.get(namespace);if (config == null) {ConfigFactory factory = m_factoryManager.getFactory(namespace);
//断点2 开始去获取configconfig = factory.create(namespace);m_configs.put(namespace, config);}}}return config;
}

6.DefaultConfigFactory.java....进入createLocalConfigRepository(namespace)

@Override
public Config create(String namespace) {DefaultConfig defaultConfig = new DefaultConfig(namespace, createLocalConfigRepository(namespace));return defaultConfig;
}

进去.然后createRemoteConfigRepository(namespace)---->new RemoteConfigRepository(namespace);

LocalFileConfigRepository createLocalConfigRepository(String namespace) {if (m_configUtil.isInLocalMode()) {logger.warn("==== Apollo is in local mode! Won't pull configs from remote server for namespace {} ! ====",namespace);return new LocalFileConfigRepository(namespace);}
//断点8return new LocalFileConfigRepository(namespace, createRemoteConfigRepository(namespace));
}RemoteConfigRepository createRemoteConfigRepository(String namespace) {return new RemoteConfigRepository(namespace);
}

7.RemoteConfigRepository.java--->进入this.trySync();

public RemoteConfigRepository(String namespace) {m_namespace = namespace;m_configCache = new AtomicReference<>();m_configUtil = ApolloInjector.getInstance(ConfigUtil.class);m_httpUtil = ApolloInjector.getInstance(HttpUtil.class);m_serviceLocator = ApolloInjector.getInstance(ConfigServiceLocator.class);remoteConfigLongPollService = ApolloInjector.getInstance(RemoteConfigLongPollService.class);m_longPollServiceDto = new AtomicReference<>();m_remoteMessages = new AtomicReference<>();m_loadConfigRateLimiter = RateLimiter.create(m_configUtil.getLoadConfigQPS());m_configNeedForceRefresh = new AtomicBoolean(true);m_loadConfigFailSchedulePolicy = new ExponentialSchedulePolicy(m_configUtil.getOnErrorRetryInterval(),m_configUtil.getOnErrorRetryInterval() * 8);gson = new Gson();this.trySync();this.schedulePeriodicRefresh();this.scheduleLongPollingRefresh();
}

8.RemoteConfigRepository.java------>loadApolloConfig();

@Override
protected synchronized void sync() {Transaction transaction = Tracer.newTransaction("Apollo.ConfigService", "syncRemoteConfig");try {ApolloConfig previous = m_configCache.get();
//断点10ApolloConfig current = loadApolloConfig();//reference equals means HTTP 304if (previous != current) {logger.debug("Remote Config refreshed!");m_configCache.set(current);this.fireRepositoryChange(m_namespace, this.getConfig());}if (current != null) {Tracer.logEvent(String.format("Apollo.Client.Configs.%s", current.getNamespaceName()),current.getReleaseKey());}transaction.setStatus(Transaction.SUCCESS);} catch (Throwable ex) {transaction.setStatus(ex);throw ex;} finally {transaction.complete();}
}

继续进入loadApolloConfig.

private ApolloConfig loadApolloConfig() {if (!m_loadConfigRateLimiter.tryAcquire(5, TimeUnit.SECONDS)) {//wait at most 5 secondstry {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {}}String appId = m_configUtil.getAppId();String cluster = m_configUtil.getCluster();String dataCenter = m_configUtil.getDataCenter();Tracer.logEvent("Apollo.Client.ConfigMeta", STRING_JOINER.join(appId, cluster, m_namespace));int maxRetries = m_configNeedForceRefresh.get() ? 2 : 1;long onErrorSleepTime = 0; // 0 means no sleepThrowable exception = null;//断点11 此处进入获取元服务信息List<ServiceDTO> configServices = getConfigServices();String url = null;for (int i = 0; i < maxRetries; i++) {List<ServiceDTO> randomConfigServices = Lists.newLinkedList(configServices);Collections.shuffle(randomConfigServices);//Access the server which notifies the client firstif (m_longPollServiceDto.get() != null) {randomConfigServices.add(0, m_longPollServiceDto.getAndSet(null));}for (ServiceDTO configService : randomConfigServices) {if (onErrorSleepTime > 0) {logger.warn("Load config failed, will retry in {} {}. appId: {}, cluster: {}, namespaces: {}",onErrorSleepTime, m_configUtil.getOnErrorRetryIntervalTimeUnit(), appId, cluster, m_namespace);try {m_configUtil.getOnErrorRetryIntervalTimeUnit().sleep(onErrorSleepTime);} catch (InterruptedException e) {//ignore}}
//生成访问元服务的url
//http://10.10.10.56:8080/configs/spring-boot-logger/default/application?ip=10.10.10.56url = assembleQueryConfigUrl(configService.getHomepageUrl(), appId, cluster, m_namespace,dataCenter, m_remoteMessages.get(), m_configCache.get());logger.debug("Loading config from {}", url);HttpRequest request = new HttpRequest(url);Transaction transaction = Tracer.newTransaction("Apollo.ConfigService", "queryConfig");transaction.addData("Url", url);try {
//将url访问元服务HttpResponse<ApolloConfig> response = m_httpUtil.doGet(request, ApolloConfig.class);m_configNeedForceRefresh.set(false);m_loadConfigFailSchedulePolicy.success();transaction.addData("StatusCode", response.getStatusCode());transaction.setStatus(Transaction.SUCCESS);if (response.getStatusCode() == 304) {logger.debug("Config server responds with 304 HTTP status code.");return m_configCache.get();}
//获取元服务返回的结果数据ApolloConfig result = response.getBody();logger.debug("Loaded config for {}: {}", m_namespace, result);return result;} catch (ApolloConfigStatusCodeException ex) {
//省略}}
9.回到断点10...

10.回到//断点8...

LocalFileConfigRepository(namespace, createRemoteConfigRepository(namespace));

11一路退出..

config = factory.create(namespace);

12一路退出..

Config config = ConfigService.getConfig(namespace);13一路退出..
composite.addPropertySource(configPropertySourceFactory.getConfigPropertySource(namespace, config));

14.多个namespace多次循环

15最后将配置放到environment.PropertySources

environment.getPropertySources().addFirst(composite);

Springboot 通过Apollo-client加载配置的过程相关推荐

  1. springboot 加载配置信息(静态)

    springboot 加载配置信息(静态) 举例:动态设置验证码过期时间 application-uat.properties配置(文件路径:/src/main/resources/applicati ...

  2. springboot 读取配置文件_使用 @ConfigurationProperties 在 Spring Boot 中加载配置

    本文地址: 使用 @ConfigurationProperties 在 Spring Boot 中加载配置 使用 Spring Boot 加载配置文件的配置非常便利,我们只需要使用一些注解配置一下就能 ...

  3. 如何正确控制springboot中bean的加载顺序总结

    1.为什么需要控制加载顺序 springboot遵从约定大于配置的原则,极大程度的解决了配置繁琐的问题.在此基础上,又提供了spi机制,用spring.factories可以完成一个小组件的自动装配功 ...

  4. SpringBoot项目中图片加载失败

    SpringBoot项目中图片加载失败 这个原因有很多,比如你的拦截器,过滤了静态资源. 如果你感觉自己的前端代码没有问题,配置也没有问题,可能是由于你后期导入的图片还没有被加载到target文件夹中 ...

  5. SpringBoot profile及其配置文件加载顺序

    1.多Profile文件 Profile是Spring对不同环境提供不同配置功能的支持,可以通过激活.默认使用application.properties的配置: 指定参数等方式快速切换环境 多pro ...

  6. SpringBoot项目静态图片加载浏览器不显示问题解决方案

    SpringBoot项目静态图片加载浏览器不显示问题解决方案 项目结构如下: 我是通过Maven创建的以Thymeleaf为模板引擎创建的SpringBoot Web项目,发现加载的图片在浏览器不显示 ...

  7. java自定义上下文对象_Java框架_Spring应用上下文对象加载配置

    我们都知道IOC是spring框架的核心,主要作用是控制反转,把我们需要的对象从容器中提供给我们,但是IOC是如何加载我们所需要的对象的? Spring容器是IOC容器的一种,它通过Applicati ...

  8. logstash 自动重新加载配置

    自动重新加载配置 为了可以自动检测配置文件的变动和自动重新加载配置文件,需要在启动的时候使用以下命令: ./bin/lagstash -f configfile.conf --config.reloa ...

  9. 大话PHP设计模式:类自动载入、PSR-0规范、链式操作、11种面向对象设计模式实现和使用、OOP的基本原则和自动加载配置...

    一.类自动载入 SPL函数 (standard php librarys) 类自动载入,尽管 __autoload() 函数也能自动加载类和接口,但更建议使用 spl_autoload_registe ...

最新文章

  1. SQL删除一个数据库内所有表的数据保留表结构
  2. Python计算机视觉:第八章 图像类容分类
  3. 【转载】selenium webdriver进行元素定位
  4. dummy.php 下载,internal dummy connection
  5. etymology-I
  6. 6 月 4 日!苹果 WWDC 2018 或重点推出 iOS 12 系统
  7. Python - 快速理解汉诺塔
  8. gps天线拆解图片_GPS天线原理
  9. Matlab根据滤波器系数画出幅频特性曲线
  10. 图像处理——Haar特征
  11. CAD贱人工具箱插件免费下载
  12. 一组绝对有益于科研的随想录(转载)
  13. Normal Map中的值, Tangent Space, 求算 Tangent 与 Binormal 与 TBN Matrix
  14. MacBook不借助显示器通过u盘将openwrt安装到软路由硬盘
  15. Mac终端命令和连接服务器
  16. 5分绩点转4分_搞笑图片集:这才是4个兄弟分5块饼的正确答案吧
  17. 湖人行--(kobe bryant)
  18. 微软远程桌面0x104_如何处理WIN10上的远程桌面错误0x104教程
  19. Sybase数据库自动备份的实现
  20. 【若依RuoYi短信验证码登录】汇总

热门文章

  1. 大名鼎鼎的OceanBase居然在买Star了?
  2. Mac电脑打开隔空投送并传送文件的技巧
  3. 解决iPhone的隔空投送无法识别mac
  4. mysql 无法正常关闭_mysql无法正常关闭问题追查
  5. 一款好的游戏开发IDE是什么样子?Rider使用体验和建议
  6. Deepin20.9 在线安装qt6.5.1
  7. 单链表和内存布局及Java代码实现
  8. 电动汽车BMS中SOH和SOP估算策略总结
  9. WPS中 文字公式不对齐 解决方案
  10. Javascript数组的创建