apollo配置中心之--spring boot如何加载apollo

一、启动类上加入@EnableApollo注解

流程如下:
在这里插入图片描述

1.1、PropertySourcesProcessor#initializePropertySources()从apollo服务端拉取配置封装成confg对象加入到environment中

private static final String APOLLO_PROPERTY_SOURCE_NAME = "ApolloPropertySources";
protected void initializePropertySources() {
    if (environment.getPropertySources().contains(APOLLO_PROPERTY_SOURCE_NAME)) {
      //已经加载过了,返回
      return;
    }
    CompositePropertySource composite = new CompositePropertySource(APOLLO_PROPERTY_SOURCE_NAME);

    //sort by order asc
    ImmutableSortedSet<Integer> orders = ImmutableSortedSet.copyOf(NAMESPACE_NAMES.keySet());
    Iterator<Integer> iterator = orders.iterator();
    //遍历每个命名空间
    while (iterator.hasNext()) {
      int order = iterator.next();
      for (String namespace : NAMESPACE_NAMES.get(order)) {
      //获取命名空间的配置对象--》从远程服务获取
        Config config = ConfigService.getConfig(namespace);

        composite.addPropertySource(new ConfigPropertySource(namespace, config));
      }
    }
    //加到spring 环境对象中,后面注入的时候 就可以从environment对象中获取apollo配置的值
    environment.getPropertySources().addFirst(composite);
  }

1.1.1、ConfigService.getConfig(namespace)拉取对应namespace配置方法

public Config getConfig(String namespace) {
    Config config = m_configs.get(namespace);
    if (config == null) {
      synchronized (this) {
        config = m_configs.get(namespace);
        if (config == null) {
        //获取配置工厂对象,反射创建DefaultConfigFactory对象返回
          ConfigFactory factory = m_factoryManager.getFactory(namespace);
          //调用create方法,返回配置对象
          config = factory.create(namespace);
          m_configs.put(namespace, config);
        }
      }
    }

    return config;
  }

1.1.2、factory.create创建配置工厂,并返回拉取到的远程配置

@Override
  public Config create(String namespace) {
    DefaultConfig defaultConfig =
    //createLocalConfigRepository(namespace)创建本地配置仓库,apollo会从远程拉取配置后,缓存到本地
        new DefaultConfig(namespace, createLocalConfigRepository(namespace));
    return defaultConfig;
  }

1.1.3、createLocalConfigRepository(namespace)创建本地配置仓库,而本地仓库的配置来源于远程配置,即:从远程拉取配置 再缓存到本地

createLocalConfigRepository(namespace)创建本地配置仓库,而这个本地仓库的配置来源,来源于远程,apollo会从远程拉取配置后,缓存到本地。有点类似于 装饰器模式。 本地配置仓库 装饰了远程配置仓库

LocalFileConfigRepository createLocalConfigRepository(String namespace) {
//根据应用程序配置的env环境 判断是否本地模式,一般都不是本地模式
//本地模式--》从固定目录下读取配置文件构造本地配置仓库缓存
//非本模式---》从远程服务读取配置,然后构造本地仓库缓存
//m_configUtil.isInLocalMode()放通过spi构造ProviderManager (用于管理provider的对象),这个对象构造方法中初始化了3种 配置env环境的proiver,1、从//META-INF/app.properties文件读取2、从/opt/settings/server.properties文件读取,3、从网络读取
//默认从/opt/settings/server.properties文件中读取。这个方法又分优先级 jvm property > 操作系统变量--> server.properties配置文件
    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);
    }
    return new LocalFileConfigRepository(namespace, createRemoteConfigRepository(namespace));
  }

1.1.4、createRemoteConfigRepository(namespace)构造远程仓库

RemoteConfigRepository createRemoteConfigRepository(String namespace) {
//查看它的构造方法
    return new RemoteConfigRepository(namespace);
  }

new RemoteConfigRepository(namespace);

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_loadConfigRateLimiter = RateLimiter.create(m_configUtil.getLoadConfigQPS());
    //从调用远程http接口,获取远程配置
    this.trySync();
    //创建一个周期定时任务,调用trSync方法
    this.schedulePeriodicRefresh();
    //while循环中,创建一个长连接 获取远程是否有更新,如果在超时时间范围内有返回,说明配置文件有更新,那么调用trySync方法。如果超时 那么while循环再次发起这个长连接
    this.scheduleLongPollingRefresh();
  }

1.1.5、 this.trySync()从调用远程http接口,获取远程配置

protected synchronized void sync() {
    Transaction transaction = Tracer.newTransaction("Apollo.ConfigService", "syncRemoteConfig");

    try {
      //获取本地版本
      ApolloConfig previous = m_configCache.get();
      //从远程获取最新版本
      ApolloConfig current = loadApolloConfig();

      //如果不同,那么触发更新
      if (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();
    }
  }

1.1.6、创建一个周期定时任务schedulePeriodicRefresh,调用trSync方法

private void schedulePeriodicRefresh() {
        m_configUtil.getRefreshInterval(), m_configUtil.getRefreshIntervalTimeUnit());
    m_executorService.scheduleAtFixedRate(
        new Runnable() {
          @Override
          public void run() {
            //每隔一个刷新时间调用 检测有没有同步
            trySync();
          }
        }, m_configUtil.getRefreshInterval(), m_configUtil.getRefreshInterval(),
        m_configUtil.getRefreshIntervalTimeUnit());
  }

1.1.7、创建一个长连接 获取远程实时更新scheduleLongPollingRefresh

m_longPollingService.submit(new Runnable() {
  @Override
  public void run() {
     //发起一个长链接 监听更新
    doLongPollingRefresh(appId, cluster, dataCenter, secret);
  }
});
private void doLongPollingRefresh(String appId, String cluster, String dataCenter, String secret) {
	  while (!m_longPollingStopped.get() && !Thread.currentThread().isInterrupted()) {
	      url =assembleLongPollRefreshUrl(lastServiceDto.getHomepageUrl(), appId, cluster, dataCenter,
                m_notifications);
         final HttpResponse<List<ApolloConfigNotification>> response =
            m_httpUtil.doGet(request, m_responseType);
            //如果200表示的更新,那么通知
         if (response.getStatusCode() == 200 && response.getBody() != null) {
	          updateNotifications(response.getBody());
	          updateRemoteNotifications(response.getBody());
	          transaction.addData("Result", response.getBody().toString());
	          notify(lastServiceDto, response.getBody());
        }
        //304表示超时,没有更新,继续上面的while,再发起一个长链接
        if (response.getStatusCode() == 304 && random.nextBoolean()) {
          lastServiceDto = null;
        }
	  }
}

1.2、流程如下

在这里插入图片描述

二、apollo客户端如何同步服务端服务修改

详情可查看,apollo配置中心之-如何启动源码及Config Service 通知客户端配置变化源码解析----客户端监听

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值