深入理解Apollo核心机制之配置读取——前言

前言

Apollo是当下较为火热的配置中心,顾名思义自然是管理配置的,那么它是如何获取配置的呢?本文会简单介绍相关机制,很多东西自然解释得不到位,后续会有单独章节深追源码看具体实现的。

配置获取方式

Apollo有两种方式获取配置:
1)客户端定时请求Config Service的配置读取接口;
2)客户端长轮询Config Service的配置变更通知接口,当客户端收到变更通知之后会立即轮询Config Service的配置读取接口。

关键核心类

  1. com.ctrip.framework.apollo.internals.RemoteConfigRepository :实现AbstractConfigRepository抽象类,远程配置Repository。实现从Config Service拉取配置,并缓存在内存中。并且定时+实时刷新缓存。
  2. com.ctrip.framework.apollo.internals.RemoteConfigLongPollService :长轮询的核心类,就是拼接URL请求Config Service的notifications/v2接口,等待获取配置更新通知。
  3. com.ctrip.framework.apollo.biz.message.ReleaseMessageScanner :客户端感知配置发生变化的核心类。

客户端如何感知配置变化?

  1. Admin Service在配置发布后会往ReleaseMessage表插入一条消息记录;
  2. Config Service会启动一个线程定时扫描ReleaseMessage表(默认是1秒)查看是否有新的消息记录;
  3. Config Service发现有新的消息记录,就会通知到所有的消息监听器;
  4. 消息监听器得到配置发布的消息后,就会通知对应的客户端。(之后就是客户端主动去拉取配置了)

Config Service如何通知客户端?

通知采用基于Http长连接实现,主要分为以下几个步骤:

  1. 客户端会发起Http请求到Config Service的notifications/v2接口;
  2. notifications/v2接口通过Spring DeferredResult把请求挂起,不会立即返回;
  3. 如果在60秒内没有该客户端关心的配置发布,那么会返回Http状态码304给客户端;
  4. 如果发现配置有修改,则会调用DeferredResult的setResult方法,传入有配置变化的namespace信息,同时该请求会立即返回;
  5. 客户端从返回结果中获取到配置变化的namespace后,会立即请求Config Service获取该namespace的最新配置。

总结

咱们知道Apollo有专属的数据库:ApolloPortalDB、ApolloConfigDB,所以数据都是放在这些库里的,自然包括配置信息。所以无非就是新增配置信息(发布)的时候,某表有新数据,与此同时客户端定时去扫描查看这张表看看有没有更新,如果有更新那么就通知客户端,告诉客户端哪个namespace的配置更新了,然后客户端再去主动调用拉去配置的接口获取新的配置;当然这保证的实时性,期间可能会发生各种问题导致配置有问题,咱们客户端还有一种拉取配置的方式那就是每5分钟也会主动调用拉取配置的接口获取配置,这样就保证了配置的数据一致性。不得不提的是,Apollo还有本地文件缓存和内存缓存(默认不开启),这就保证了Apollo服务不可用的时候短时间内也不会影响到客户端(因为客户端依旧可以从缓存中读取配置),设计非常的严谨与优秀!

知识Tip

上文中提到的DeferredResult,可能有的小伙伴没有接触过。我在这里简单地举个例子,希望你能明白~
类似于,你去超市买一样东西,但是此时这东西没货,那么你留个电话给服务员,自己去做别的事情了,而服务员会不停地问仓库有没有货了,当有货的时候他会打电话告诉你(类似调用setResult方法),这时候你就会屁颠屁颠地拿着货走了。(比喻可能不够恰当和严谨,但是一般精辟就行,希望你能领悟~)
用正式一点的技术用语来描述呢就是,DeferredResult:当一个请求到达API接口,如果该API接口的return返回值是DeferredResult,在没有超时或者DeferredResult对象设置setResult时,接口不会返回但是Servlet容器线程会结束DeferredResult另起线程来进行结果处理(即这种操作提升了服务短时间的吞吐能力)。如此一来,这个请求不会占用服务连接池太久,如果超时或者setResult,接口会立即返回。

posted @ 2021-03-22 13:43  程序员deepz  阅读(1475)  评论(0编辑  收藏  举报