Tomcat进程占用CPU过高的解决方法

 更新时间:2021年08月04日 10:12:07   作者:JavaEdge.  
本文主要介绍了Tomcat进程占用CPU过高的解决方法,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

CPU经常会成为系统性能的瓶颈,可能:

  • 内存泄露导致频繁GC,进而引起CPU使用率过高
  • 代码Bug创建了大量的线程,导致CPU频繁上下文切换

通常所说的CPU使用率过高,隐含着一个用来比较高与低的基准值,比如

  • JVM在峰值负载下的平均CPU利用率40%
  • CPU使用率飙到80%就可认为不正常

JVM进程包含多个Java线程:

  • 一些在等待工作
  • 另一些则正在执行任务

最重要的是找到哪些线程在消耗CPU,通过线程栈定位到问题代码
如果没有找到个别线程的CPU使用率特别高,考虑是否线程上下文切换导致了CPU使用率过高。

案例

程序模拟CPU使用率过高 - 在线程池中创建4096个线程

在Linux环境下启动程序:

java -Xss256k -jar demo-0.0.1-SNAPSHOT.jar

线程栈大小指定为256KB。对于测试程序来说,操作系统默认值8192KB过大,因为需要创建4096个线程。

使用top命令,我们看到Java进程的CPU使用率达到了961.6%,注意到进程ID是55790。

用更精细化的top命令查看这个Java进程中各线程使用CPU的情况:

#top -H -p 55790

可见,有个叫“scheduling-1”的线程占用了较多的CPU,达到了42.5%。因此下一步我们要找出这个线程在做什么事情。

为了找出线程在做什么,用jstack生成线程快照。
jstack输出较大,一般将其写入文件:

jstack 55790 > 55790.log

打开55790.log,定位到第4步中找到的名为 scheduling-1 的线程,其线程栈:

看到AbstractExecutorService#submit这个函数调用,说明它是Spring Boot启动的周期性任务线程,向线程池中提交任务,该线程消耗了大量CPU。

上下文切换开销?

经历上述过程,往往已经可以定位到大量消耗CPU的线程及bug代码,比如死循环。但对于该案例:Java进程占用的CPU是961.6%, 而“scheduling-1”线程只占用了42.5%的CPU,那其它CPU被谁占用了?

第4步用top -H -p pid命令看到的线程列表中还有许多名为“pool-1-thread-x”的线程,它们单个的CPU使用率不高,但是似乎数量比较多。你可能已经猜到,这些就是线程池中干活的线程。那剩下的CPU是不是被这些线程消耗了呢?

还需要看jstack的输出结果,主要是看这些线程池中的线程是不是真的在干活,还是在“休息”呢?

发现这些“pool-1-thread-x”线程基本都处WAITING状态。

  • Blocking指的是一个线程因为等待临界区的锁(Lock或者synchronized关键字)而被阻塞的状态,请你注意的是处于这个状态的线程还没有拿到锁
  • Waiting指的是一个线程拿到了锁,但需等待其他线程执行某些操作。比如调用了Object.wait、Thread.join或LockSupport.park方法时,进入Waiting状态。前提是这个线程已经拿到锁了,并且在进入Waiting状态前,os层面会自动释放锁,当等待条件满足,外部调用了Object.notify或者LockSupport.unpark方法,线程会重新竞争锁,成功获得锁后才能进入到Runnable状态继续执行。

回到我们的“pool-1-thread-x”线程,这些线程都处在“Waiting”状态,从线程栈我们看到,这些线程“等待”在getTask方法调用上,线程尝试从线程池的队列中取任务,但是队列为空,所以通过LockSupport.park调用进到了“Waiting”状态。那“pool-1-thread-x”线程有多少个呢?通过下面这个命令来统计一下,结果是4096,正好跟线程池中的线程数相等。

grep -o 'pool-2-thread' 55790.log | wc -l

剩下CPU到底被谁消耗了?
应该怀疑CPU的上下文切换开销了,因为我们看到Java进程中的线程数比较多。

下面通过vmstat命令来查看一下操作系统层面的线程上下文切换活动:

cs那一栏表示线程上下文切换次数,in表示CPU中断次数,我们发现这两个数字非常高,基本证实了我们的猜测,线程上下文切切换消耗了大量CPU。
那具体是哪个进程导致的呢?

停止Spring Boot程序,再次运行vmstat命令,会看到in和cs都大幅下降,这就证实引起线程上下文切换开销的Java进程正是55790。

总结

遇到CPU过高,首先定位哪个进程导致的,之后可以通过top -H -p pid命令定位到具体的线程。
其次还要通jstack查看线程的状态,看看线程的个数或者线程的状态,如果线程数过多,可以怀疑是线程上下文切换的开销,我们可以通过vmstat和pidstat这两个工具进行确认。

到此这篇关于Tomcat进程占用CPU过高的解决方法的文章就介绍到这了,更多相关Tomcat进程占用CPU过高内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 记一次tomcat进程cpu占用过高的问题排查记录

    记一次tomcat进程cpu占用过高的问题排查记录

    这篇文章主要介绍了记一次tomcat进程cpu占用过高的问题排查记录,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • Tomcat的Server Options选项详解

    Tomcat的Server Options选项详解

    这篇文章主要介绍了Tomcat的Server Options选项详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • 如何通过LambdaProbe实现监控Tomcat

    如何通过LambdaProbe实现监控Tomcat

    这篇文章主要介绍了如何通过LambdaProbe实现监控Tomcat,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • 详解将Web项目War包部署到Tomcat服务器基本步骤

    详解将Web项目War包部署到Tomcat服务器基本步骤

    本篇文章主要介绍了详解将Web项目War包部署到Tomcat服务器基本步骤,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • Tomcat启动核心流程示例详解

    Tomcat启动核心流程示例详解

    这篇文章主要为大家介绍了Tomcat启动核心流程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • tomcat相关配置与eclipse集成_动力节点Java学院整理

    tomcat相关配置与eclipse集成_动力节点Java学院整理

    这篇文章主要介绍了tomcat相关配置与eclipse集成_动力节点Java学院整理的相关资料,需要的朋友可以参考下
    2017-07-07
  • 如何提升Idea启动速度与Tomcat日志乱码问题

    如何提升Idea启动速度与Tomcat日志乱码问题

    这篇文章主要介绍了提升Idea启动速度与Tomcat日志乱码问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • 在Windows10中安装TomCat的教程图解

    在Windows10中安装TomCat的教程图解

    Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。这篇文章主要介绍了在Windows10中安装TomCat的教程图解,需要的朋友可以参考下
    2019-11-11
  • 解决“Unable to start embedded Tomcat“错误的完整指南

    解决“Unable to start embedded Tomcat“错误的完整

    在使用Spring Boot开发应用程序时,有时可能会遇到"Unable to start embedded Tomcat"的错误,这可能是由多种原因引起的,本文将详细介绍这个错误的常见原因以及解决方法,帮助你快速解决问题并顺利启动应用程序
    2023-10-10
  • WIN2003下IIS6集成一个或多个Tomcat的方法

    WIN2003下IIS6集成一个或多个Tomcat的方法

    由于IIS配置与PHP的集成网上很多,所以这里我只记录IIS与JAVA服务器Tomcat的集成,需要的朋友可以参考下
    2014-07-07

最新评论