CacheData
首先需要讲解到的就是CacheData。所有的配置信息和监听器都存放在CacheData中,包括一些操作方法。所以它不仅仅是一个存储的配置信息的实体,也包括了操作,获取,更新这个信息的功能。以下通过代码分析一下它的私有变量。
publicclassCacheData {
// 线程池的最大线程数 staticfinalintCONCURRENCY=5;
// 线程工厂,表明创建的是后台线程并赋予名字 staticThreadFactoryinternalNotifierFactory= r -> {
Threadt=newThread(r);
t.setName("nacos.client.cachedata.internal.notifier");
t.setDaemon(true);
return t;
};
// 是否初始化快照staticboolean initSnapshot;
// 静态块,获取属性值static {
initSnapshot = NacosClientProperties.PROTOTYPE.getBoolean("nacos.cache.data.init.snapshot", true);
LOGGER.info("nacos.cache.data.init.snapshot = {} ", initSnapshot);
}
// 内部的通知线程池staticfinalThreadPoolExecutorINTERNAL_NOTIFIER=newThreadPoolExecutor(0, CONCURRENCY, 60L, TimeUnit.SECONDS,
newSynchronousQueue<>(), internalNotifierFactory);
// 名称privatefinal String name;
// 过滤器链privatefinal ConfigFilterChainManager configFilterChainManager;
// dataIdpublicfinal String dataId;
// grouppublicfinal String group;
// tenantpublicfinal String tenant;
// 监听器privatefinal CopyOnWriteArrayList<ManagerListenerWrap> listeners;
// 配置信息的md5值privatevolatile String md5;
// 是否使用本地缓存privatevolatilebooleanisUseLocalConfig=false;
// 上次配置修改时间,long类型privatevolatilelong localConfigLastModified;
// 配置信息privatevolatile String content;
// 加密数据的keyprivatevolatile String encryptedDataKey;
// 修改时间privatevolatileAtomicLonglastModifiedTs=newAtomicLong(0);
// taskIdprivateint taskId;
// 是否初始化privatevolatilebooleanisInitializing=true;
// 是否和服务端同步privatevolatilebooleanisSyncWithServer=false;
// 是否丢失privatevolatilebooleanisDiscard=false;
// typeprivate String type;
}
复制代码
CacheData的一些方法和成员变量的解释说明会在调用的时候再具体说明,这里只是需要有个印象,它不仅仅是对配置信息的保存,也包含了一些其他的状态位和操作的方法和变量。
ClientWorker
对CacheData有了初步印象后,我们就开始重点分析一下ClientWorker。先看它的构造方法。
publicClientWorker(final ConfigFilterChainManager configFilterChainManager, ServerListManager serverListManager,
final NacosClientProperties properties)throws NacosException {
this.configFilterChainManager = configFilterChainManager;
init(properties);
// 创建一个用于配置服务端的Rpc通信客户端
agent = newConfigRpcTransportClient(properties, serverListManager);
intcount= ThreadUtils.getSuitableThreadCount(THREAD_MULTIPLE);
ScheduledExecutorServiceexecutorService= Executors
.newScheduledThreadPool(Math.max(count, MIN_THREAD_NUM), r -> {
Threadt=newThread(r);
t.setName("com.alibaba.nacos.client.Worker");
t.setDaemon(true);
return t;
});
// 配置了一个异步处理线程池
agent.setExecutor(executorService);
// 调用start方法
agent.start();
}
publicvoidstart()throws NacosException {
// 认证服务,主要是通过Secret Key和Access Key做认证用
securityProxy.login(this.properties);
this.executor.scheduleWithFixedDelay(() -> securityProxy.login(properties), 0,
this.securityInfoRefreshIntervalMills, TimeUnit.MILLISECONDS);
// 内部启动
startInternal();
}
publicvoidstartInternal() {
executor.schedule(() -> {
while (!executor.isShutdown() && !executor.isTerminated()) {
try {
listenExecutebell.poll(5L, TimeUnit.SECONDS);
if (executor.isShutdown() || executor.isTerminated()) {
continue;
}
// 执行配置监听
executeConfigListen();
} catch (Throwable e) {
LOGGER.error("[ rpc listen execute ] [rpc listen] exception", e);
}
}
}, 0L, TimeUnit.MILLISECONDS);
}
复制代码
在创建ClientWorker的时候构造方法中做了如下操作:
初始化了本地变量和参数
创建了一个远程通信的客户端
配置了一个定时线程池,并且对需要认证的服务端做了认证
执行配置的监听,如果没有监听器的变动,则等待5s处理一次
继续看executeConfigListen()方法。
publicvoidexecuteConfigListen() {
// 存放含有listen的cacheData
Map<String, List<CacheData>> listenCachesMap = newHashMap<&g