深入理解Apollo核心机制之配置读取——轮询
前两篇内容
《深入理解Apollo核心机制之配置读取——前言》
《深入理解Apollo核心机制之配置读取——ConfigService定时扫描》
概述
读取配置除了默认5分钟间隔去轮询接口拉取配置,还有客户端主动长轮询ConfigService,等待通知后主动拉取配置。本文就看看客户端是如何开始客户端轮询的,以及轮询中的具体细节。
RemoteConfigRepository#RemoteConfigRepository(String namespace) 初始化工作
该构造函数会初始化命名空间,配置缓存等许多基本信息,同时有一步就是将自己(this)注册进RemoteConfigLongPollService,因为后续长轮询其实是该Service统一去做的。
RemoteConfigRepository#scheduleLongPollingRefresh() 注册接口
m_namespace是在初始话的时候设置的,它表示该Repository所对应的命名空间。
RemoteConfigLongPollService#submit(String namespace, RemoteConfigRepository remoteConfigRepository) 正式注册并开始开启长轮询准备工作
RemoteConfigLongPollService#startLongPolling() 准备正式开启长轮询
RemoteConfigLongPollService#doLongPollingRefresh(String appId,String cluster,String dataCenter) 长轮询开始
通过封装了Eureka的MetaService获取ConfigService集群,然后硬核负载均衡打到ConfigService的长轮询接口开始长轮询等待通知,如果关注的namespace有更新,则会做一些更新本地成员变量的操作,最重要的就是会通知相关的注册进来的Repository去主动拉取配置。这就是客户端长轮询等待通知,发现有配置更新后主动去拉取配置的一个基本流程。注意,当发送请求到长轮询接口的时候会被ConfigService hold住,直到响应或者超时。稍后再看NotificationControllerV2那边的流程。我们先关注客户端长轮询、获取通知、主动轮询拉取配置接口的过程。
RemoteConfigLongPollService#notify(ServiceDTO lastServiceDTO, List notifications) 长轮询结果通知客户端
根据通知中传递的namespaceName,去之前注册的Repository集合Map拿到关注该namespaceName的Repository
RemoteConfigRepository#onLongPollNotified(ServiceDTO longPollNotifiedServiceDto, ApolloNotificationMessages remoteMessages) 准备同步配置
AbstractConfigRepository#trySync() 准备同步配置
缓存中拿一份,远程拉取一份,比较后更新内存缓存。并通知
RemoteConfigRepository#loadApolloConfig() 拉取配置
拼接URL请求ConfigService接口拉取配置
AbstractConfigRepository#fireRepositoryChange(String namespace, Properties newProperties) 通知监听器配置改变(实时修改配置)
回到长轮询,话说客户端拼接请求打到ConfigService的NotificationControllerV2#pollNotification接口后是什么情况呢?
NotificationControllerV2#pollNotification 拉取(等待)通知
有一个Multimap<String,DeferredResultWrapper>,以key(appId+cluster+namespace)和List
每一次请求,都会创建一个DeferredResultWrapper,然后通过一系列操作最后将自己注册进上述集合,等待handleMessage调用setResult(结束长轮询)或者超时,这样就把Result返回给客户端了。
客户端就可以获得变更通知从而知道是什么namespace变更了,然后会主动拉取对应配置。