cpu飙升怎么排查

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cpu飙升怎么排查相关的知识,希望对你有一定的参考价值。

一、引子
对于互联网公司,线上CPU飙升的问题很常见(例如某个活动开始,流量突然飙升时),按照本文的步骤排查,基本1分钟即可搞定!特此整理排查方法一篇,供大家参考讨论提高。

二、问题复现
线上系统突然运行缓慢,CPU飙升,甚至到100%,以及Full GC次数过多,接着就是各种报警:例如接口超时报警等。此时急需快速线上排查问题。

三、问题排查
不管什么问题,既然是CPU飙升,肯定是查一下耗CPU的线程,然后看看GC。

3.1 核心排查步骤

1.执行“top”命令:查看所有进程占系统CPU的排序。极大可能排第一个的就是咱们的java进程(COMMAND列)。PID那一列就是进程号。

2.执行“top -Hp 进程号”命令:查看java进程下的所有线程占CPU的情况。

3.执行“printf "%x\n 10"命令 :后续查看线程堆栈信息展示的都是十六进制,为了找到咱们的线程堆栈信息,咱们需要把线程号转成16进制。例如,printf "%x\n 10-》打印:a,那么在jstack中线程号就是0xa.

4.执行 “jstack 进程号 | grep 线程ID” 查找某进程下-》线程ID(jstack堆栈信息中的nid)=0xa的线程堆栈信息。如果“"VM Thread" os_prio=0 tid=0x00007f871806e000 nid=0xa runnable”,第一个双引号圈起来的就是线程名,如果是“VM Thread”这就是虚拟机GC回收线程了

5.执行“jstat -gcutil 进程号 统计间隔毫秒 统计次数(缺省代表一致统计)”,查看某进程GC持续变化情况,如果发现返回中FGC很大且一直增大-》确认Full GC! 也可以使用“jmap -heap 进程ID”查看一下进程的堆内从是不是要溢出了,特别是老年代内从使用情况一般是达到阈值(具体看垃圾回收器和启动时配置的阈值)就会进程Full GC。

6.执行“jmap -dump:format=b,file=filename 进程ID”,导出某进程下内存heap输出到文件中。可以通过eclipse的mat工具查看内存中有哪些对象比较多。

3.2 原因分析

1.内存消耗过大,导致Full GC次数过多

执行步骤1-5:

多个线程的CPU都超过了100%,通过jstack命令可以看到这些线程主要是垃圾回收线程-》上一节步骤2

通过jstat命令监控GC情况,可以看到Full GC次数非常多,并且次数在不断增加。--》上一节步骤5

确定是Full GC,接下来找到具体原因:

生成大量的对象,导致内存溢出-》执行步骤6,查看具体内存对象占用情况。

内存占用不高,但是Full GC次数还是比较多,此时可能是代码中手动调用 System.gc()导致GC次数过多,这可以通过添加 -XX:+DisableExplicitGC来禁用JVM对显示GC的响应。

2.代码中有大量消耗CPU的操作,导致CPU过高,系统运行缓慢;

执行步骤1-4:在步骤4jstack,可直接定位到代码行。例如某些复杂算法,甚至算法BUG,无限循环递归等等。

3.由于锁使用不当,导致死锁。

执行步骤1-4:如果有死锁,会直接提示。关键字:deadlock.步骤四,会打印出业务死锁的位置。

造成死锁的原因:最典型的就是2个线程互相等待对方持有的锁。

4.随机出现大量线程访问接口缓慢。

代码某个位置有阻塞性的操作,导致该功能调用整体比较耗时,但出现是比较随机的;平时消耗的CPU不多,而且占用的内存也不高。

思路:

首先找到该接口,通过压测工具不断加大访问力度,大量线程将阻塞于该阻塞点。
参考技术A

打开系统任务管理,然后点击一下排序,检查哪个系统进程cpu利用率最高就可以了。

参考技术B 中央处理器(CPU,英语:Central Processing Unit),是电子计算机的主要设备之一,电脑中的核心配件。其功能主要是解释计算机指令以及处理计算机软件中的数据。电脑中所有操作都由CPU负责读取指令,对指令译码并执行指令的核心部件。

  计算机求解问题是通过执行程序来实现的。程序是由指令构成的序列,执行程序就是按指令序列逐条执行指令。一旦把程序装入主存储器(简称主存)中,就可以由CPU自动地完成从主存取指令和执行指令的任务。



  一条指令的功能往往是由计算机中的部件执行一序列的操作来实现的。CPU要根据指令的功能,产生相应的操作控制信号,发给相应的部件,从而控制这些部件按指令的要求进行动作。

  外频是CPU的基准频率,单位是MHz。CPU的外频决定着整块主板的运行速度。通俗地说,在台式机中,所说的超频,都是超CPU的外频(当然一般情况下,CPU的倍频都是被锁住的)相信这点是很好理解的。但对于服务器CPU来讲,超频是绝对不允许的。前面说到CPU决定着主板的运行速度,两者是同步运行的,如果把服务器CPU超频了,改变了外频,会产生异步运行,(台式机很多主板都支持异步运行)这样会造成整个服务器系统的不稳定。
参考技术C 建议清理CPU灰尘,检查导热硅脂是否正常。
另外,可以用AIDA64查看CPU温度,或者在Bios中查看温度。
有些软件查看温度不准确。可以用手靠近散热器感受一下温度是否真有那么高。
参考技术D 你这个首先需要看自己的CPU性能是否太老,核心和线程都不够情况下运行程序占用率就高,你先在任务管理器中查看一下什么程序占用CPU频率高,如果查不到就有可能是中病毒了,最好的办法就是重新格式化硬盘再重新装系统,还是出现一样问题就是你CPU性能不够,需要升级更换CPU才行,

记一次new ArrayList导致的cpu飙升问题排查

点击关注公众号,Java干货及时送达

来源:juejin.cn/post/7139202066362138654

  • 前言

  • 当时场景

  • 正常的jvm监控曲线图

  • 产生问题的jvm监控曲线图

  • 具体分析

  • 结束语


昨天线上容器突然cpu飙升,也是第一次排查这种问题所以记录一下~

前言

首先问题是这样的,周五正在写文档,突然收到了线上报警,发现cpu占用达到了90多,上平台监控系统查看容器,在jvm监控中发现有一个pod在两个小时内产生了61次youngGc一次fullGc,这个问题特别严重且少见,由于我之前也没有排查过此类问题,所以也是百度,但整个过程也有一些自己的思考,所以跟大家分享一下~

当时场景

我先给大家看一下一副正常的gc曲线监控(为保密性,我自己按照平台监控画了出来):

正常的jvm监控曲线图

正常的jvm监控曲线图

产生问题的jvm监控曲线图

产生问题的jvm监控曲线图

可以看的出来,正常情况下该系统很少gc(具体看业务系统使用情况、jvm内存分配),但是在图二中出现了大量异常的gc情况甚至触发了fullGc,所以我当时立马进行了分析。

具体分析

首先异常gc的情况只出现在一个pod上(系统有多个pod),在监控系统找到对应的pod,进入pod内部查看问题原因,排查问题一定要冷静

  1. 进入pod之后,输入top查看各linux进程对系统资源的使用情况(因我这是事后补稿,资源使用不高,大家看步骤即可)

图片
  1. 分析资源使用情况在当时的情况下

top

当时我的pid为1的进程cpu上到了130(多核)那我认定就是java应用出问题了,control+c退出继续往下走

  1. 输入top -H -p pid 通过此命令可以查看实际占用CPU最高的的线程的id,pid为刚才资源使用高的pid号

top -H -p pid

  1. 出现具体线程的资源使用情况,表格里的pid代表线程的id,我们称他为tid

tid

  1. 我记得当时的tip为746(上述图片只是我给大家重复步骤),使用命令printf "%x\\n" 746,将线程tid转换为16进制

tid转换为16进制

因为我们线程id号在堆栈里是16进制的所以需要做一个进制转换

  1. 输入jstack pid | grep 2ea >gc.stack

jstack pid | grep 2ea >gc.stack

jstack

解释一下,jstack是jdk给提供的监控调优小工具之一,jstack会生成JVM当前时刻的线程快照,然后我们可以通过它查看某个Java进程内的线程堆栈信息,之后我们把堆栈信息通过管道收集2ea线程的信息,然后将信息生成为gc.stack文件,我随便起的,随意

  1. 当时我先cat gc.stack 发现数据有点多在容器里看不方便,于是我下载到本地浏览,因为公司对各个机器的访问做了限制,我只能用跳板机先找到一台没用的机器a,把文件下载到a然后我再把a里的文件下载到本地(本地访问跳板机OK),先输入python -m SimpleHTTPServer 8080,linux自带python,这个是开启一个简单http服务供外界访问

开启http服务

然后登录跳板机,使用curl下载curl -o http://ip地址/gcInfo.stack

为方便演示,我在图中把ip换了一个假的

curl

之后用同样的方法从本地下载跳板机就可以了,记得关闭python开启的建议服务嗷

  1. 把文件下载到了本地,打开查看编辑器搜索2ea,找到nid为2ea的堆栈信息

找到nid为2ea的堆栈信息

之后找到对应的impl根据行数分析程序

  1. 发现是在文件异步导出excel的时候,导出接口使用了公共列表查询接口,列表接口查询数据最多为分页200一批,而导出数据量每个人的权限几万到十几万不等

导出excel

并且该判断方法使用了嵌套循环里判断,且结合业务很容易 get 不到 value,Java 下的new ArrayList 就是返回一个 List 集合(好像不用说这么细 (;一_一 ),在整个方法结束之前,产生的 lists生命周期还在所以发生多次gc触发重启之后还影响到了别的pod。然后对代码进行了fix,紧急上线,问题解决~

结束语

遇到生产问题,大家不要害怕,遇到问题先保证服务是否可用,然后通过有限的信息层层解析,找出最终的问题。如果你会 arthas,排查起来会更轻松!

以上是关于cpu飙升怎么排查的主要内容,如果未能解决你的问题,请参考以下文章

cpu飙升问题排查思路

cpu突然飙升故障排查思路

Java_cpu飙升排查

记一次new ArrayList导致的cpu飙升问题排查

记一次new ArrayList导致的cpu飙升问题排查

关于CPU飙升时的排查过程