分布式配置中心Apollo源码分析

1.前言

在日常开发过程中,通常会把经常发生变更的配置放在分布式配置中心apollo中。一天突然有一个疑问,应用配置文件中和Apollo都存在相同的配置,为什么会使用apollo上的配置,而非使用应用配置文件中的配置,带着这个疑问,开启了一场阅读apollo源码的旅途。

其实这个问题在SpringBoot配置你不知道的秘密这篇文章中可以找到答案,apollo配置原理和spring.config.additional-location属性原理类似,只要把配置放入Environment的最前面就可以实现。

2.apollo应用初始化

在apollo客户端jar包的spring.factories文件中可以看到这样的配置

ApolloApplicationContextInitializer作为apollo应用上下文的初始化类,实现了ApplicationContextInitializer接口,表明着会在SpringBoot的启动过程中会进行初始化

2.1 阅读注释

在阅读源代码之前,先来看看相关注释,作为代码的灵魂,可以在阅读源码的过程中为我们指引方向

2.2 初始化

要想开启apollo功能,必须要指定apollo.bootstrap.enabled属性

通过分析可以了解到初始化过程可以分为5个步骤:

  • 读取指定命名空间
  • 遍历命名空间
  • 读取命名空间中的配置
  • 将读取到的配置组装成PropertySource
  • PropertySource添加到environment对象中

Environment对象中维护了一个private final List<PropertySource<?>> propertySourceList = new CopyOnWriteArrayList<>();列表,读取配置的时候会遍历列表从前往后进行读取,读取到结果直接返回。这也就可以说明apollo上和本地文件中有相同的配置时,读取的时候会读取apollo上的配置而不读取本地配置的原因。

3.读取配置

配置读取其实就是客户端向服务器端拉取配置的一个过程,客户端告诉服务器端自己需要哪个应用(app.id) + 哪个集群(default) + 哪个命名空间(namespace)下的配置,服务器端从表中读取满足条件的配置,然后返回给客户端,客户端缓存在内存中,方便后续频繁读取。

整体就是这样的一个思路,下面就来看看具体的代码实现,主要实现类RemoteConfigRepository

3.1 主动同步配置

3.1.1 查询服务信息

向服务端发送一个http请求,服务端从注册中心中拉取对应服务注册表返回给客户端

客户端拿着返回的服务地址信息就可以进行下一步操作

3.1.2 拉取配置

随机向服务列表中的一台服务发起请求

告诉服务器端要拉取配置对应的app.id + cluster + namespace,服务器端从对应的表中拉取最新符合条件的记录

3.2 长轮询服务刷新配置

image-20201024170241676a

客户端会向服务器端发起一个请求,服务器端发现客户端的配置不是最新的,返回200给客户端,客户端再向服务器端发起拉取配置请求;服务器端发现客户端的配置已经是最新的了,返回304,客户端不会向服务器端发送拉取配置请求

3.2.1 长连接实现

那么服务器端是如何实现长连接的呢?使用DeferredResult挂起请求

服务器端将客户端对命名空间的请求都存放在Map中

private final Multimap<String, DeferredResultWrapper> deferredResults =
      Multimaps.synchronizedSetMultimap(TreeMultimap.create(String.CASE_INSENSITIVE_ORDER, Ordering.natural()));
复制代码

服务器端发现有最新结果,就设置结果,此时服务器端会将结果响应给客户端;没有结果请求就被挂起,在60s内服务器端通过handleMessage设置了结果,客户端就可以拿到正常响应结果,然后向服务器端发起拉取最新配置请求;在60s内服务器端没有设置结果,客户端会拿到304响应结果,此结果表示服务器端没有最新的配置,客户端不需要向服务器端发起拉取配置请求。

长连接的好处就是服务器端有最新的配置,可以及时通知客户端向服务器端拉取最新配置。

3.3 周期性主动同步配置

apollo除了依靠长连接通知客户端拉取配置外,还会周期性每隔5分钟主动向服务器端发送拉取最新配置的请求,从而保证推送不可用的情况下,可以通过主动拉取的方式来获取最新配置数据。



转载自 https://juejin.cn/post/6887125578525671431

 
posted @ 2021-08-17 16:27  looyee  阅读(395)  评论(0编辑  收藏  举报