前兩篇內容
《深入理解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變更了,然后會主動拉取對應配置。