在网上没找到该类的资料,只好自己解读,然后整理出来供其他有需要的小伙伴阅读。
NacosWatch的实例化
在spring-cloud-starter-alibaba-nacos-discovery-2.2.6.RELEASE.jar下spring.factories里引入了NacosDiscoveryClientConfiguration,
NacosDiscoveryClientConfiguration里实例化了NacosWatch,
NacosWatch的start()调用时机
因为NacosWatch实现了SmartLifecycle接口,所以在启动完Tomcat后会调用start(),
public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactoryAware {
//...
private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName, boolean autoStartupOnly) {
Lifecycle bean = lifecycleBeans.remove(beanName);
if (bean != null && bean != this) {
String[] dependenciesForBean = getBeanFactory().getDependenciesForBean(beanName);
for (String dependency : dependenciesForBean) {
doStart(lifecycleBeans, dependency, autoStartupOnly);
}
if (!bean.isRunning() &&
(!autoStartupOnly || !(bean instanceof SmartLifecycle) || ((SmartLifecycle) bean).isAutoStartup())) {
try {
bean.start(); //NacosWatch
}
}
//...
}
NacosWatch的start()作用
start()是该类的核心方法,也是这篇文章的核心。
public class NacosWatch implements ApplicationEventPublisherAware, SmartLifecycle {
//Map<服务名,监听>
private Map<String, EventListener> listenerMap = new ConcurrentHashMap<>(16);
//...
@Override
public void start() {
//CAS锁,以只执行一次
if (this.running.compareAndSet(false, true)) {
//listenerMap里添加注册服务的监听
EventListener eventListener = listenerMap.computeIfAbsent(buildKey(),
event -> new EventListener() {
@Override
public void onEvent(Event event) {
//如果是NamingEvent事件,则选择注册服务的第一个实例,更新metadata
if (event instanceof NamingEvent) {
List<Instance> instances = ((NamingEvent) event)
.getInstances();
Optional<Instance> instanceOptional = selectCurrentInstance(
instances);
instanceOptional.ifPresent(currentInstance -> {
resetIfNeeded(currentInstance);
});
}
}
});
//反射实例化NamingService ,这里是NacosNamingService
NamingService namingService = nacosServiceManager
.getNamingService(properties.getNacosProperties());
try {
/**
* 1.向InstancesChangeNotifier通知里订阅该服务的实例改变的通知
* 2.向nacos服务端发起一次/v1/ns/instance/list的HTTP请求,获取注册服务的列表
* 3.开启定时任务更新注册服务的实例列表
*/
namingService.subscribe(properties.getService(), properties.getGroup(),
Arrays.asList(properties.getClusterName()), eventListener);
}
catch (Exception e) {
log.error("namingService subscribe failed, properties:{}", properties, e);
}
//延迟30s,且每隔30s向nacos服务端发布一个心跳事件
this.watchFuture = this.taskScheduler.scheduleWithFixedDelay(
this::nacosServicesWatch, this.properties.getWatchDelay());
}
}
//...
}