今天下午突然 出现 测试环境 cpu飙高,干到了 60%,其他项目 响应时间明显变长。出问题的项目是 需要连接各个不同nacos 和不同的 namespace 进行对应操作的 一个项目。

       首先 这 cpu高了,直接top -Hp 看看定位到 进程id,然后 执行 jstack 进程id -> 1.txt,看到堆栈信息 ,下面提示信息有很多:


"com.alibaba.nacos.client.config.security.updater" #2269 daemon prio=5 os_prio=0 tid=0x00007fa3ec401800 nid=0x8d85 waiting on condition [0x00007fa314396000]
   java.lang.Thread.State: TIMED_WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000f7f3eae0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
        at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
        at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)


但是上面这个提示信息 显示 是 线程内部的,而且是nacos client 内部的,关键字 com.alibaba.nacos.client.config.security.updater ServerHttpAgent 类的方法:


// init executorService
this.executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        t.setName("com.alibaba.nacos.client.config.security.updater");
        t.setDaemon(true);
        return t;
    }
});


这是构造方法,应该只初始化一次的,往上debug,NacosConfigService 类中调用了,debug 看什么时候调用了 不就行了,项目初始化的时候 调用了一次,30s后 发现又是一次调用,往回debug,代码如下


scheduler.schedule("定时校对灰度nacos 配置", () -> loadGrayConfig(grayFileName),
    1800, 1800, TimeUnit.SECONDS);


/**
 * 灰度配置更新 解决 网络隔离的问题
 *
 * @param grayFileName 灰度文件的名称
 */
private void loadGrayConfig(String grayFileName) {
    synchronized (this) {
        System.err.println("loadGrayConfig datetime: " + DateUtils.formatDate(new Date()));
        //刷一次 缓存 重新获取nacos 内容 赋值
        grayConfigManager.loadNoCache(grayFileName);
    }
}


这当时是为了灰度功能,定时数据校验用的 用了一个线程池,当时以为用了线程池 妥妥的。。。还特意调用的 Nocache 方法,让他创建新的nacos Config对象,做数据校对

但是每调用一次 NacosFactory.createConfigService(properties) ,nacos config 构造器就会开一个线程,就导致了这个问题

这里可能你要问了你说为了防止网络隔离才加的这个调度任务。

修复方法:

我对nacos config 连接进行 遍历查找 是否存活,不存活 我就shutdown,然后生成一个新的,而不是这种全部生成一遍,毕竟人家 构造器开了线程。。。。跑到测试环境 看看效果(CPU),稳定了,后期在长期观察下