整体流程

约定
- 通知编号 = 
ReleaseMessage.id - Watch Key = 
ReleaseMessage.message 
推送客户端发布消息
推送配置流程图

ReleaseMessageScanner
com.ctrip.framework.apollo.biz.message.ReleaseMessageScanner ,实现 org.springframework.beans.factory.InitializingBean 接口,ReleaseMessage 扫描器,被 Config Service 使用。
初始化 Scan 任务
1  | 
  | 
fireMessageScanned
#fireMessageScanned(List<ReleaseMessage> messages) 方法,触发监听器,处理 ReleaseMessage 们。代码如下:
1  | private void fireMessageScanned(List<ReleaseMessage> messages) {  | 
NotificationControllerV2
com.ctrip.framework.apollo.configservice.controller.NotificationControllerV2 ,实现 ReleaseMessageListener 接口,通知 Controller ,仅提供 notifications/v2 接口。
1  | 
  | 
客户端拉取配置
拉取配置流程图

RemoteConfigRepository
com.ctrip.framework.apollo.internals.RemoteConfigRepository ,实现 AbstractConfigRepository 抽象类,远程配置 Repository 。实现从 Config Service 拉取配置,并缓存在内存中。并且,定时 + 实时刷新缓存。
构造方法
1  | public RemoteConfigRepository(String namespace) {  | 
sync
#sync() 实现方法,从 Config Service 同步配置
1  | 
  | 
RemoteConfigLongPollService
com.ctrip.framework.apollo.internals.RemoteConfigLongPollService ,远程配置长轮询服务。负责长轮询 Config Service 的配置变更通知 /notifications/v2 接口。当有新的通知时,触发 RemoteConfigRepository ,立即轮询 Config Service 的配置读取 /configs/{appId}/{clusterName}/{namespace:.+} 接口。
1  | public boolean submit(String namespace, RemoteConfigRepository remoteConfigRepository) {  | 
startLongPolling
#startLongPolling() 方法,启动长轮询任务
1  | private void startLongPolling() {  | 
长轮询到新的通知消息,会更新本地缓存,通知观察者(RemoteConfigRepository),触发监听事件
1  | // 更新通知消息中,命名空间对应的最新通知id  | 
onLongPollNotified
当 RemoteConfigLongPollService 长轮询到该 RemoteConfigRepository 的 Namespace 下的配置更新时,会回调 #onLongPollNotified(ServiceDTO, ApolloNotificationMessages) 方法
1  | // 监听事件  | 
服务端拉取配置

ConfigController
1  | (value = "/{appId}/{clusterName}/{namespace:.+}")  | 

加载配置
1  | 
  | 
判断是否关联类型的namespace,如果是需要拉取被关联的配置的发布记录
1  | private boolean namespaceBelongsToAppId(String appId, String namespaceName) {  |