一、问题描述
在使用Nacos作为注册中心情况下,客户端启动后频繁打印get changedGroupKeys:[]
c.a.n.client.config.impl.ClientWorker : get changedGroupKeys:[]
c.a.n.client.config.impl.ClientWorker : get changedGroupKeys:[]
c.a.n.client.config.impl.ClientWorker : get changedGroupKeys:[]
c.a.n.client.config.impl.ClientWorker : get changedGroupKeys:[]
c.a.n.client.config.impl.ClientWorker : get changedGroupKeys:[]
c.a.n.client.config.impl.ClientWorker : get changedGroupKeys:[]
c.a.n.client.config.impl.ClientWorker : get changedGroupKeys:[]
c.a.n.client.config.impl.ClientWorker : get changedGroupKeys:[]
c.a.n.client.config.impl.ClientWorker : get changedGroupKeys:[]
先贴解决方案,再来分析原因
二、解决:nacos配置中加上禁用心跳日志
logging:
level:
com.alibaba.nacos.client.config.impl: WARN
三、问题分析
从日志可以看出 get changedGroupKeys:[] 是从c.a.n.client.config.impl.ClientWorker对象中打印出来的,贴出ClientWorker类中打印get changedGroupKeys:[]方法代码:
public class ClientWorker {
//长轮询任务,检测服务端配置文件是否更改,30秒超时
class LongPollingRunnable implements Runnable {
private int taskId;
public LongPollingRunnable(int taskId) {
this.taskId = taskId;
}
@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);
}
}
}
// check server config
List<String> changedGroupKeys = checkUpdateDataIds(cacheDatas, inInitializingCacheList);
//可以看出这里打印的心跳日志 get changedGroupKeys:[]
LOGGER.info("get changedGroupKeys:" + changedGroupKeys);
for (String groupKey : changedGroupKeys) {
String[] key = GroupKey.parseKey(groupKey);
String dataId = key[0];
String group = key[1];
String tenant = null;
if (key.length == 3) {
tenant = key[2];
}
try {
//30秒超时,30秒一检测,仔细发现能看出每隔30秒打印一遍get changedGroupKeys:[]心跳日志
String[] ct = getServerConfig(dataId, group, tenant, 3000L);
CacheData cache = cacheMap.get().get(GroupKey.getKeyTenant(dataId, group, tenant));
cache.setContent(ct[0]);
if (null != ct[1]) {
cache.setType(ct[1]);
}
LOGGER.info("[{}] [data-received] dataId={}, group={}, tenant={}, md5={}, content={}, type={}",
agent.getName(), dataId, group, tenant, cache.getMd5(),
ContentUtils.truncateContent(ct[0]), ct[1]);
} catch (NacosException ioe) {
String message = String.format(
"[%s] [get-update] get changed config exception. dataId=%s, group=%s, tenant=%s",
agent.getName(), dataId, group, tenant);
LOGGER.error(message, ioe);
}
}
for (CacheData cacheData : cacheDatas) {
if (!cacheData.isInitializing() || inInitializingCacheList
.contains(GroupKey.getKeyTenant(cacheData.dataId, cacheData.group, cacheData.tenant))) {
cacheData.checkListenerMd5();
cacheData.setInitializing(false);
}
}
inInitializingCacheList.clear();
//方法的最后会再把LongPollingRunnable提交执行,递归,再执行
executorService.execute(this);
} catch (Throwable e) {
// If the rotation training task is abnormal, the next execution time of the task will be punished
LOGGER.error("longPolling error : ", e);
executorService.schedule(this, taskPenaltyTime, TimeUnit.MILLISECONDS);
}
}
}
}
分析:从ClientWorker 代码中分析出,nacos客户端和服务端会通过心跳来检测nacos服务端的配置文件是否发生变化,这也是nacos动态配置实现的原理,客户端通过定时线程长轮询达到动态配置的效果,可以看到这个日志的级别为INFO,我们把nacos的日志级别改为WARN,这样就不会每次心跳检测都打印get changedGroupKeys:[]了。