从NacosConfigService的构造方法里
this.worker = new ClientWorker(this.agent, this.configFilterChainManager, properties);
这行代码开始,看下ClientWorker的初始化做了什么:
public ClientWorker(final HttpAgent agent, final ConfigFilterChainManager configFilterChainManager,
final Properties properties) {
// http代理
this.agent = agent;
// 过滤器
this.configFilterChainManager = configFilterChainManager;
// Initialize the timeout parameter
// 初始化配置
init(properties);
this.executor = Executors.newScheduledThreadPool(1, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("com.alibaba.nacos.client.Worker." + agent.getName());
t.setDaemon(true);
return t;
}
});
// cpu核数的线程,用来做长轮询的,每次检查配置,如果LongPollingRunnable任务的配置缓存超过一定数量,默认3000个,就要去开启一个新任务去检查配置
// Runtime.getRuntime().availableProcessors()获取cpu核数
this.executorService = Executors
.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(), new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("com.alibaba.nacos.client.Worker.longPolling." + agent.getName());
t.setDaemon(true);
return t;
}
});
// 10毫秒的任务,检查配置信息 LongPollingRunnable
this.executor.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
try {
checkConfigInfo();
} catch (Throwable e) {
LOGGER.error("[" + agent.getName() + "] [sub-check] rotate check error", e);
}
}
}, 1L, 10L, TimeUnit.MILLISECONDS);
}
这里定义了两个线程池,executorService这里只定义了,还没放入线程,用来做长轮询的,核心线程数是CPU核数;executor每10毫秒执行一次checkConfigInfo方法。
我们看一下checkConfigInfo这个方法:
public void checkConfigInfo() {
// Dispatch taskes.
// 监听的数量
int listenerSize = cacheMap.get().size();
// Round up the longingTaskCount.
// 监听数量/3000 向上取整
int longingTaskCount = (int) Math.ceil(listenerSize / ParamUtil.getPerTaskConfigSize());
if (longingTaskCount > currentLongingTaskCount) {
for (int i = (int) currentLongingTaskCount; i < longingTaskCount; i++) {
taskIdSet.add(i);
// 循环3000次,建一个新的
// LongPollingRunnable 长链接监听
// 每个LongPollingRunnable默认可以负责3000个监听器的轮询
executorService.execute(new LongPollingRunnable(i));
}
} else if (longingTaskCount < currentLongingTaskCount) {
for (int i = longingTaskCount; i < (int) currentLongingTaskCount; i++) {
taskIdSet.remove(i);
}
}
currentLongingTaskCount = longingTaskCount;
}
ParamUtil.getPerTaskConfigSize()这个默认是3000。
这里的逻辑是这样的,根据监听器的数量建立长轮询任务,每3000个监听建一个任务并放入到executorService里。
监听器在cacheMap里,后面我们看addListener方法时会看到写入这个缓存的操作。
我们看一下LongPollingRunnable这个:
@Override
public void run() {
List<CacheData> cacheDatas = new ArrayList<CacheData>();
List<String> inInitializingCacheList = new ArrayList<String>();
try {
// check failover config
for (CacheData cacheData : cacheMap.get().values()) {
//属于当前长轮询任务的
if (cacheData.getTaskId() == taskId) {
cacheDatas.add(cacheData);
try {
checkLocalConfig(cacheData);
//用本地配置
if (cacheData.isUseLocalConfigInfo()) {
//有改变的话会通知
cacheData.checkListenerMd5();
}
} catch (Exception e) {
LOGGER.error("get local config info error", e);
}
}
}
//获取有变化的配置列表dataid+group,访问的url是/listener
// check server config
List<String> changedGroupKeys = checkUpdateDataIds(cacheDatas, inInitializingCacheList);
if (!CollectionUtils.isEmpty(changedGr