专栏首页后端开发随笔谈谈Tomcat占用cpu高的问题

谈谈Tomcat占用cpu高的问题

问题现场

测试环境tomcat进程占用CPU一直持续99%,但是通过jstack查看log,也没有任何线程死锁的情况。 此时通过$catalina_home/bin/shutdown.sh脚本无法正常停止tomcat。

这是什么原因?

线程死锁 vs 线程死循环

验证线程死锁不会导致CPU持续高负载

// 验证线程死锁是否会导致CPU占用率一直居高不下
public class LockTest {
    private Object alock = new Object();  // a锁
    private Object block = new Object();  // b锁

    public static void main(String[] args) {
        new LockTest().start();
    }

    private void start() {
        new Thread(new ThreadA()).start();
        new Thread(new ThreadB()).start();
    }

    private void sleepOfSeconds(int seconds) {
        try {
            Thread.sleep(seconds * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    // 在线程A中先获取a锁,再获取b锁
    class ThreadA implements Runnable {
        private String name = "ThreadA";
        @Override
        public void run() {
            synchronized (alock) {
                System.out.println(name + " get alock");
                sleepOfSeconds(50);
            }
            System.out.println(name + " release alock");
            System.out.println(name + " waiting block");
            synchronized (block) {
                System.out.println(name + " get block");
            }
            System.out.println(name + " release block");
        }
    }

    // 在线程B中先获取b锁,再获取a锁
    class ThreadB implements Runnable {
        private String name = "ThreadB";
        @Override
        public void run() {
            synchronized (block) {
                System.out.println(name + " get block");
                sleepOfSeconds(10);
            }
            System.out.println(name + " release block");
            System.out.println(name + " waiting alock");
            synchronized (alock) {
                System.out.println(name + " get alock");
            }
            System.out.println(name + " release alock");
        }
    }
}

线程进入死锁状态时,不会导致CPU持续高负载,实际上当线程进入死锁之后是等待获取对象所被执行,此时CPU是空闲的。

导致CPU负载持续高的原因是线程进入了死循环,导致CPU持续在工作,此时线程的状态应该是Runnable,而不是Blocked。

排查Java进程导致CPU持续高的方法

在Linux环境下,通过如下步骤可以实现对Java进程CPU持续高负载的问题排查:

  1. 通过jps命令找到Java进程ID,并使用top命令确定CPU占用高的进程是否为jps命令找到的Java进程。
  2. 通过ps -mp pid -o THREAD,tid,time命令查看进程的线程列表,找到CPU占用最高的线程ID,并使用printf "%x\n" tid命令输出线程ID的16进制格式:tid_hex 。
  3. 通过jstack pid |grep tid_hex -A 30查看线程堆栈信息,找到处于Runnable状态的线程中执行的代码片段,就可以分析出对应导致线程死循环的原因了。

可以将上述命令整理成一个脚本工具,用于临时排查CPU高的问题,详见:https://raw.githubusercontent.com/nuccch/iToolBox/master/shell/show_java_process_thread_stack.sh

Tomcat的CPU占用高的原因总结

  1. 线程死锁和线程死循环不是一个概念,千万不要弄错。
  2. 通常来讲,对于部署到Tomcat中的应用程序,排除程序代码进入死循环的原因之外,会导致Tomcat进程CPU持续高负载的可能因素是存在大量的TCP连接请求(并发很大)。
  3. 由于应用程序出现堆内存空间不够用导致频繁GC,也会导致CPU使用率高。
  4. 如果应用日志输出非常频繁,也会导致CPU使用率持续高。

【参考】 https://www.jianshu.com/p/3160ba8e150d 记一次tomcat cpu占用率过高的问题排查 http://www.blogjava.net/hankchen/archive/2012/05/09/377735.html 线上应用故障排查之一:高CPU占用

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • mvn项目压缩打包

    通常情况下,maven打包结果为jar或war包。 如果需要一并打包配置文件等参数,通过resources配置指定需要打包的文件参数,如下示例:

    2Simple
  • 细说shiro之五:在spring框架中集成shiro

    特别地!Shiro使用了日志框架slf4j,因此需要对应配置指定的日志实现组件,如:log4j,logback等。 在此,以使用log4j为日志实现为例:

    2Simple
  • 深入浅出mybatis之启动详解

    我们知道,SqlSessionFactory是MyBatis中最为核心的组件,每个基于MyBatis的应用都是以一个SqlSessionFactory实例为中心...

    2Simple
  • Java源码阅读之ReentrantLock - lockInterruptibly和tryLock方法

    上一篇博客阅读了Java的ReentrantLock的lock和unlock,这篇分析另外三个方法lockInterruptibly、tryLock()和try...

    格子Lin
  • 死磕Java并发:深入分析synchronized的实现原理

    记得刚刚开始学习Java的时候,一遇到多线程情况就是synchronized。对于当时的我们来说,synchronized是如此的神奇且强大。我们赋予它一个名字...

    程序猿DD
  • Java程序员必备的一些流程图

    Spring作为当前Java最流行、最强大的轻量级容器框架,了解熟悉spring的生命周期非常有必要;

    猿天地
  • Java 程序员必备的一些流程图

    Spring作为当前Java最流行、最强大的轻量级容器框架,了解熟悉spring的生命周期非常有必要;

    芋道源码
  • 干货收藏 | Java程序员必备的一些流程图

    来源:juejin.im/post/5d214639e51d4550bf1ae8df

    Java团长
  • 【死磕Java并发】-----深入分析synchronized的实现原理

    记得刚刚开始学习Java的时候,一遇到多线程情况就是synchronized,相对于当时的我们来说synchronized是这么的神奇而又强大,那个时候我们赋予...

    用户1655470
  • 【死磕Java并发】-----深入分析synchronized的实现原理

    记得刚刚开始学习Java的时候,一遇到多线程情况就是synchronized,相对于当时的我们来说synchronized是这么的神奇而又强大,那个时候我们赋予...

    用户1655470

扫码关注云+社区

领取腾讯云代金券