本次解析的版本基于Nacos 1.1.0
ServiceManager是nacos naming server中service核心管理类。在启动时会执行一次本地信息到其他服务器,while(true)发生改变的service队列内容进行本地更新,同时启动对com.alibaba.nacos.naming.domains.meta.前缀的key的监听;在运行过程中,执行controller接受的相关请求的功能,完成本地状态和远程服务器同步。
首先看下整体结构,有一个大致印象
主要总启动时执行和运行时执行的功能来分析。
启动时的执行依赖于注解@PostConstruct的init()方法
@PostConstruct
public void init() {
UtilsAndCommons.SERVICE_SYNCHRONIZATION_EXECUTOR.schedule(new ServiceReporter(), 60000, TimeUnit.MILLISECONDS);
UtilsAndCommons.SERVICE_UPDATE_EXECUTOR.submit(new UpdatedServiceProcessor());
try {
Loggers.SRV_LOG.info("listen for service meta change");
consistencyService.listen(KeyBuilder.SERVICE_META_KEY_PREFIX, this);
} catch (NacosException e) {
Loggers.SRV_LOG.error("listen for service meta change failed!");
}
}
第一行代码解析:bean初始化之后,执行一次调度,调度由ServiceReporter来执行。方法首先遍历serviceMap(Map
如果service不为空,通过对该service下所有Instance实例组成的ip.getIp() + ":" + ip.getPort() + "_" + ip.getWeight() + "_"+ ip.isHealthy() + "_" + ip.getClusterName()执行md5来获得该service对应的checksum,再将service的checksum封装为Message实例msg,再将该消息同步到出自已以外的所有服务器。器质性同步的过程是通过async http post请求path /nacos/v1/ns/service/status来执行的,此处不关心执行结果,异步执行。
第一行代码思考:刚启动时执行一次同步数据到其他服务是否真的有必要?会不会导致数据落后呢?
第二行代码解析:启动一个新的UpdatedServiceProcessor线程并直接执行while (true),简单粗暴。该循环会一直尝试从LinkedBlockingDeque
第二行代码思考:此处是通过死循环遍历队列发现service改变的通知,然后再去对应的server上去获取具体的改变,这样效率会不会低?直接把改变推送过来不就是更好。
try和catch模块中的代码解析:try和catch模块:该模块主要是启动对service meta change的监听,该模块由代码consistencyService.listen(KeyBuilder.SERVICE_META_KEY_PREFIX, this);来执行,
consistencyService是ConsistencyService的对象,实际运行过程中是由DelegateConsistencyServiceImpl类的实例来执行的。 具体逻辑如下:
@Override
public void listen(String key, RecordListener listener) throws NacosException {
// this special key is listened by both:
if (KeyBuilder.SERVICE_META_KEY_PREFIX.equals(key)) {
persistentConsistencyService.listen(key, listener);
ephemeralConsistencyService.listen(key, listener);
return;
}
mapConsistencyService(key).listen(key, listener);
}
上述代码逻辑首先判断该key是否是special key,即以com.alibaba.nacos.naming.domains.meta.为前缀的key,
如果是,那么persistentConsistencyService和ephemeralConsistencyService都会启动监听;如果不是那么
根据key判断到底启动上述监听器中的哪一个。判断的具体逻辑在KeyBuilder中的matchEphemeralInstanceListKey方法中,
public static boolean matchEphemeralInstanceListKey(String key) {
return key.startsWith(INSTANCE_LIST_KEY_PREFIX + EPHEMERAL_KEY_PREFIX);
}
即,如果以com.alibaba.nacos.naming.iplist.ephemeral.为前缀的则启动ephemeralConsistencyService监听;其他情况则启动
persistentConsistencyService监听。
从上面传过来的常量来看是com.alibaba.nacos.naming.domains.meta.也就是2个监听器都会启动监听。