面试官:Tomcat 进程占用 CPU 过高怎么办?

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

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

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

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

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

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

最重要的是找到哪些线程在消耗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。

image

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

#top -H -p 55790
image

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

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

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

image

看到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的输出结果,主要是看这些线程池中的线程是不是真的在干活,还是在“休息”呢?

image

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

image
  • 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
image

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

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

image

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

那具体是哪个进程导致的呢?

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

image

总结

遇到CPU过高,首先定位哪个进程导致的,之后可以通过top -H -p pid命令定位到具体的线程。

其次还要通jstack查看线程的状态,看看线程的个数或者线程的状态,如果线程数过多,可以怀疑是线程上下文切换的开销,我们可以通过vmstat和pidstat这两个工具进行确认。

作者:JavaEdge.
原文链接:https://blog.csdn.net/qq_33589510/article/details/119304427

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352

推荐阅读更多精彩内容