定位线上故障。线程维度
-
top
-
按1,查看CPU利用率。按P(大写)按CPU占用率排序
- us:用户空间占用CPU百分比
- sy:内核空间占用CPU百分比
- ni:用户进程空间内改变过优先级的进程占用CPU百分比
- id:空闲CPU百分比
- wa:等待输入输出的CPU时间百分比
-
按H(大写),查看线程性能信息,默认按照CPU占用排序。可能会出现三种情况:
-
第一种情况,某个线程一直CPU利用率100%,则说明是这个线程有可能有死循环,那么请记住这个PID。
-
第二种情况,某个线程一直在TOP十的位置,这说明这个线程可能有性能问题。
-
第三种情况,CPU利用率TOP几的线程在不停变化,说明并不是由某一个线程导致CPU偏高。
-
-
如果是第一种情况,也有可能是GC造成,我们可以用jstat命令看下GC情况,看看是不是因为持久代或年老代满了,产生Full GC,导致CPU利用率持续飙高,命令如下。
Jstat -gcutil pid 间隔时间 打印次数
确定是gc频繁的话,可以进一步确认一下,是哪部分代码执行的时候造成了cpu飙高,用jstack命令把线程的堆栈信息打印出来:
jstack pid > t-pid.dump
dump出来的文件里面是线程对应的堆栈信息,线程id也就是nid是十六进制的,而我们用top命令看到的线程id是十进制的,所以我们要转换我们看到的线程id从十进制到十六进制:
printf "%x " pid
然后我们可以看到线程当前执行到哪段代码了,判断一下是不是这段代码导致的cpu飙高。不是的话就可以找其他原因了。
线程数过多导致线程切换频繁,加大CPU开销,问题定位
-
查看当前机器建立的TCP连接数
netstat -nat | awk '{print $6}' | sort | uniq -c | sort -n
-
使用jstack dump看看这些线程都在做什么
jstack pid > /home/t_pid.dump
-
统计下所有的线程分别处于什么状态。发现大量线程处于waiting(on object monitor)状态
grep java.lang.Thread.State t_pid.dump | awk '{print $2$3$4$5}' | sort | uniq -c
-
查看处于waiting(on object monitor)的线程信息。观察哪个程序的waiting状态比较多。
grep -A 5 'WAITING' t_pid.dump
-
找到程序的配置信息,减少核心线程数的最大值(ps:线程不是越多越好,需要结合CPU多少、处理速度、业务计算多少来确定)
<修改中间件或者程序配置>
-
重启程序,重新dump线程信息,再次进行统计,分析是否解决问题。
重复1-4
涉及到的其他命令
-
查看CPU信息
cat /proc/cpuinfo
-
查看内存信息
cat /proc/meminfo
-
查看Java线程数
ps -eLf | grep java -c
-
查看linux系统里打开文件描述符的最大值
ulimit -u
-
找到日志里TOP10的异常
grep ‘Exception’ /home/admin/logs/XX.log |awk -F':|,' ‘{print $2}’|sort |uniq -c |sort -nr|head -10
找到之后可以再用-A 2 -B 2,看定位出日志的前面2行和后面两行。