CPU负载120%

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mingyundezuoan/article/details/84844891

CPU负载120%


概述

  • 背景:生产环境服务响应缓慢,出现RPC接口超时
  • 排查:
    • 服务双机部署,登录两台日志机器,登录两台部署机器
    • 查看部署机器服务负载,
      • top 查看,同一台机器上部署三个服务
      • 其中A服务,CPU 120%
      • 查看刚出现 CPU 负载过高的时间,运维提供监控日志显示上午,查看日志,这期间发生的疑似操作
      • 定位问题,近期优化的一个批量初始化数据到缓存中的功能被触发了多次,且该功能为了快速响应,建立线程池,核心线程数10,最大线程数20,用户进行了多次点击,每一次的数据请求量都很大,上一次操作没有完成,下一次的请求即开始了

堆栈信息1

  • 查看负载高的进程
    • 进入部署服务器
    • top , 按 P ,记录CPU负载高的进程编号
  • 查看负载高的进程
    • top -Ph pid 进程编号,按P ,记录CPU负载高的线程编号
  • 线程编号转为十六进制,通过windows提供的科学计算器
  • 查看堆栈信息
    • jstack pid | grep “0xtid”

异常信息

   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x000000073e4aa000> (a java.util.concurrent.SynchronousQueue$TransferStack)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
        at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:458)
        at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:359)
        at java.util.concurrent.SynchronousQueue.take(SynchronousQueue.java:925)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)

private static final ExecutorService EXECUTOR_SERVICE = new ThreadPoolExecutor(10, 20,
            300, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(1000),
            new ThreadFactory() {
                @Override
                public Thread newThread(Runnable r) {
                    Thread t = new Thread(r);
                    t.setDaemon(true);
                    return t;
                }
            }, new ThreadPoolExecutor.CallerRunsPolicy());

根据堆栈信息配置源码跟踪问题原因定位于
服务器CPU数量 2 个,A服务中存在不同的多个线程池,功能运行过程中交叉多个线程池的运行,每个线程在规定的时间内都没有得到反馈,每个线程都在执行SQL查询,没有得到数据响应,线程挂起;不断创建新的线程执行挂起的任务,发生资源争抢,导致CPU负载过高


异常反思

  • 线程池使用要根据服务器性能合理设置,创建数量过多会导致CPU负载过高

  1. 记录一次cpu 100%线上问题排查 ↩︎

猜你喜欢

转载自blog.csdn.net/mingyundezuoan/article/details/84844891
120