Tomcat进程占用CPU过高怎么办?

简介: Tomcat进程占用CPU过高怎么办?

Kafka运维利器:深入解析AdminClient原理与实战

本文已收录在Github关注我,紧跟本系列专栏文章,咱们下篇再续!

  • 🚀 魔都架构师 | 全网30W技术追随者
  • 🔧 大厂分布式系统/数据中台实战专家
  • 🏆 主导交易系统百万级流量调优 & 车联网平台架构
  • 🧠 AIGC应用开发先行者 | 区块链落地实践者
  • 🌍 以技术驱动创新,我们的征途是改变世界!
  • 👉 实战干货:编程严选网



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。对于测试程序,os默认值8192KB过大,因为需要创建4096个线程。

top

见Java进程CPU使用率爆表:

top细查

这进程的各线程使用CPU情况:

$ top -H -p 55790

“scheduling-1”线程占较多CPU。找这线程在做啥。

jstack生成线程快照

jstack输出较大,一般将其写入文件:

jstack 55790 > 55790.log

打开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”线程有多少个呢?统计结果正好和线程池中的线程数相等:

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

剩下的CPU到底被谁消耗了?怀疑CPU的上下文切换开销了,因为看到Java进程中的线程数比较多。vmstat查看os层面的线程上下文切换活动:

  • procs:线程上下文切换次数
  • in:CPU中断次数,这俩数字非常高,基本证实猜测,线程上下文切切换消耗大量CPU。

那到底是啥进程导致的?

停止Spring Boot程序,再次运行vmstat命令:in和procs都大幅下降,说明引起线程上下文切换开销的Java进程正是55790。

总结

CPU过高,先定位啥进程导致,之后top -H -p pid定位具体线程。

还要jstack查看线程状态,看线程个数或线程状态,若线程数过多,可怀疑是线程上下文切换开销,可通过vmstat和pidstat确认。

目录
相关文章
|
Linux
Linux 查看进程PID和线程CPU和内存占用情况
Linux 查看进程PID和线程CPU和内存占用情况
1877 0
|
移动开发 Linux
Linux下如何查看哪些进程占用的CPU内存资源最多
Linux下如何查看哪些进程占用的CPU内存资源最多
527 0
|
网络协议 前端开发 调度
schedule:原来还可以这样让进程让出 CPU?
文章主要讲述通过模拟时钟中断和调度事件来优化和测试虚拟机监控器(VMM)的方法,包括流程设计、寄存器状态的保存与恢复、硬件中断处理规范等细节。
409 11
schedule:原来还可以这样让进程让出 CPU?
|
Windows
dllhost.exe进程占用CPU很高怎么解决?
全面解析dllhost.exe进程
2462 16
|
Java 对象存储 开发者
如何找出Java进程占用CPU高的元凶
本文记录了一次Java进程CPU占用率过高的问题和排查思路。
|
弹性计算 Linux 区块链
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
837 4
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
|
存储 监控
【Azure Cloud Service】在Azure云服务中收集CPU监控指标和IIS进程的DUMP方法
在使用Cloud Service服务时,发现服务的CPU占用很高,在业务请求并不大的情况下,需要直到到底是什么进程占用了大量的CPU资源,已经如何获取IIS进程(w3wp.exe)的DUMP文件?
317 8
|
Linux Python
在Linux中,如何查找系统中占用CPU最高的进程?
在Linux中,如何查找系统中占用CPU最高的进程?
在Linux中,如何查看占用CPU最多的进程?
在Linux中,如何查看占用CPU最多的进程?
|
存储 缓存 NoSQL
Redis性能优化问题之优化 Redis fork 耗时严重的问题,如何解决
Redis性能优化问题之优化 Redis fork 耗时严重的问题,如何解决