1. 简述
测试环境压测发现cpu飙升,cpu升高通常情况表示代码中有 大量计算逻辑 、 死循环 、 内存泄漏引起的频繁GC 也可导致。因此,这类问题可以从以上几个方面排查。
2. dump的概念
在问题定位和性能分析过程中,dump文件有很大帮助。dump文件记录了jvm运行期间内存状态,线程执行执行情况,常用的有thread dump,heap dump。
简单来说,thread dump是记录线程执行信息,heap dump是记录jvm内存信息。
thread dump : 主要记录JVM在某一时刻各个线程执行的情况,以栈的形式显示,是一个文本文件。通过对thread dump文件可以分析出程序的问题出现在什么地方,从而定位具体的代码然后进行修正。thread dump需要结合占用系统资源的线程id进行分析才有意义。
heap dump : 主要记录了在某一时刻JVM堆中对象使用的情况,即某个时刻JVM堆的快照,是一个二进制文件,主要用于分析哪些对象占用了太多的堆空间,从而发现导致内存泄漏的对象。
dump文件具有实时性,因此需要再服务出现问题时候生成。并且多生成几个文件进行对比分析~(后面有thread dump生成脚本)
3. CPU 飙升问题排查
## 1. 查看运行进程,并找到消耗CPU 最高的进程pid
## 2. 根据上一步的进程pid 定位该进程中某个线程的 CPU 消耗情况
top -Hp [pid]
## 或者 根据pid,查看占用cpu较高的tid
ps -mp pid -o THREAD,tid,time | sort -nr -k 2
## 3. 将tid转化为16进制(thread dump中以十六进制显示线程信息)输出16进制pid
printf '%x\n' pid
## 4.直接使用jstack 定位某个进程中线程的执行情况,并用颜色高亮颜色显示
jstack pid |grep 'nid' -A 30 –color
## 我们也可以将该进程信息导出到 文件中,查看线程执行情况
jstack -l [进程 ID] >jstack.log
## 再从文件中进行排查
cat jstack.log |grep 'nid' -C5 –color
通过查看线程执行信息一般即可定位到问题:
如果占用cpu过高的线程为GC线程,这时就需要考虑内存泄漏引起的cpu升高问题(需要观察gc状态,及jmap生成heap dump文件,通过MAT/jvisualvm分析内存占用大对象。
REF-1:JVM性能调优监控工具jps、jmap、jstack、jstat使用详解
REF-2: jstat命令查看jvm的GC情况
如果占用cpu的线程不是gc线程,查看线程信息需要关注线程是否正在执行,未执行的线程通常不会引起cpu升高。由于thread dump信息具有实时性,上一时刻占用cpu高的线程id,在查看线程信息时可能已经执行完毕,已经不是占用cpu高的线程,因此可通过脚本实时监控监控线程状态。(下面脚本可实时打印占用cpu过高线程执行信息,
REF-3:使用jstack定位线程堆栈信息
#check pid
if test -z "$($JAVA_HOME/bin/jps -l | cut -d ' ' -f 1 | grep $pid)"; then
echo "process $pid not exist"
#line num
line_num=$2
if test -z $line_num; then
line_num=10
# generate stack & thread file
stackfile=stack$pid.dump
threadsfile=thread$pid.dump
$JAVA_HOME/bin/jstack -l $pid >> $stackfile
ps -mp $pid -o THREAD,tid,time | sort -nr -k 2 | awk '{if ($1!="USER" && $2!="0.0" && $8!="-") print $8;}' | xargs printf "%x\n" >> $threadsfile
tids="$(cat $threadsfile)"
for tid in $tids; do
echo "-------------thread($pid)----------------"
cat $stackfile | grep $tid -A $line_num
rm -rf $stackfile
rm -rf $threadsfile
技术能量站
35.9k