深入理解Apollo核心机制之配置读取——ConfigService定时扫描
概述
之前我们了解了,客户端会每秒(默认)长轮询Config Service,等待通知,然后去主动拉取配置文件。本文主要跟进Config Service主动轮询ReleaseMessage表,并通知对应监听器的源码,最终终止客户端长轮询的源码。附上之前的链接《深入理解Apollo核心机制之配置读取——前言》
监听器介绍
Config Service中有一些类实现了ReleaseMessageListener接口,并重写了handleMessage()方法,当ConfigService扫描到有新的配置发布的时候,就会轮询通知所有实现了上述监听器接口的监听器,调用handleMessage()方法。我们要了解的和客户端长轮询的监听器的类便是NotificationControllerV2。其它的监听器在配置发布的时候也有自己的职责,这里不过多介绍,我们只会查看NotificationControllerV2中的handleMessage()方法,了解它在接到通知的时候是如何处理消息的。
监听器注册
监听器结构
ReleaseMessageScanner#afterPropertiesSet() 开启扫描任务
首先看到ReleaseMessageScanner类,这个类就是做这件事情的。我们会发现它会开启一个定时扫描的任务(默认1秒间隔),具体看下面源码。
ReleaseMessageScanner#scanMessages() 扫描条件
ReleaseMessageScanner#scanAndSendMessages() 扫描并发送通知
Config Service会查出”当前最大扫描ID“后500条数据(根据ID升序),如果没有数据,则代表上次扫描之后,没有新的配置发布,如果有新的配置发布则会通知监听器。
必备Tip
客户端发起长轮询是请求NotificationControllerV2的pollNotification接口,经过一系列处理,会将请求的客户端保存下来。(Map形式,key为"{appId}+{clusterName}+{namespaceName}",value为List
下图代码便是该监听器的handleMessage()源码了,它会根据收到的”message",提取appId、clusterName、namespaceName,轮询通知根据key得到的DeferredResultWrapper集合(调用setResult()方法)。从而将通知信息(DeferredResult<ResponseEntity<List