上篇说到Nacos对于服务注册和发现的支持是通过NamingService接口来实现的,对应的实现类是NacosNamingService,本篇详细介绍这个类。
先上一个结构图简单看一下这个类的结构,有个大体的了解:
看一下初始化代码:
private void init(Properties properties) throws NacosException {
ValidatorUtils.checkInitParam(properties);
this.namespace = InitUtils.initNamespaceForNaming(properties);
InitUtils.initSerialization();
initServerAddr(properties);
InitUtils.initWebRootContext();
initCacheDir();
initLogName(properties);
// 事件调度
this.eventDispatcher = new EventDispatcher();
// 服务代理
this.serverProxy = new NamingProxy(this.namespace, this.endpoint, this.serverList, properties);
// 心跳
this.beatReactor = new BeatReactor(this.serverProxy, initClientBeatThreadCount(properties));
// 主机服务
this.hostReactor = new HostReactor(this.eventDispatcher, this.serverProxy, beatReactor, this.cacheDir,
isLoadCacheAtStart(properties), initPollingThreadCount(properties));
}
主要就是针对上图中的各组件进行初始化。下面一个个分析
EventDispatcher
主要用来做事件发布的。里面维护了一个changedServices阻塞队列,初始化时启动了一个无限循环的独立线程:
public EventDispatcher() {
// Notifier 任务
this.executor = Executors.newSingleThreadExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, "com.alibaba.nacos.naming.client.listener");
thread.setDaemon(true);
return thread;
}
});
this.executor.execute(new Notifier());
}
这个Notifier线程的作用就是一直从阻塞队列changedServices中获取数据,拿到就发NamingEvent事件通知:
private class Notifier implements Runnable {
@Override
public void run() {
while (!closed) {
ServiceInfo serviceInfo = null;
try {
// 阻塞任务
serviceInfo = changedServices.poll(5, TimeUnit.MINUTES);
} catch (Exception ignore) {
}
if (serviceInfo == null) {
continue;
}
try {
// 监听器列表
List<EventListener> listeners = observerMap.get(serviceInfo.getKey());
if (!CollectionUtils.isEmpty(listeners)) {
for (EventListener listener : listeners) {
List<Instance> hosts = Collections.unmodifiableList(serviceInfo.getHosts());
// 发送监听事件
listener.onEvent(new NamingEvent(serviceInfo.getName(), serviceInfo.getGroupName(),
serviceInfo.getClusters(), hosts));
}
}
} catch (Exception e) {
NAMING_LOGGER.error("[NA] notify error for service: " + serviceInfo.getName() + ", clusters: "
+ serviceInfo.getClusters(), e);
}
}
}
}
serviceChanged方法会往队列中添加元素: