备注:此文章参考《Java并发编程的艺术》
有很多问题在开发环境下并不会出现,在生产环境下才会出现,而在生产环境下又不能调试代码,只能根据线上日志,系统状态,dump线程来定位问题
一.查看每一个进程的状态
使用命令:top
user:表示当前登录该机器的用户数
load average:一分钟负载,五分钟负载,十分钟负载(每隔5秒钟检查一次活跃的进程数,然后按特定算法计算出的数值,这个数除以逻辑CPU的数量,结果高于5的时候就表明系统在超负荷运转)
第二行表示:系统一共有255个进程,3个处于运行状态,252个处于休眠状态,0个处于停止状态,0个僵尸进程
第三行表示:
1.8%us(user):用户空间占用CPU的百分比
3.0%sy(system):内核空间占用CPU的百分比
0.0%ni(nice):改变过优先级的进程占用CPU的百分比
95.2%id(idle):空闲CPU百分比
0.0%wa(wait):IO等待占用CPU的百分比
0.0%hi(hardware interrupts):硬中断占用CPU的百分比
0.0%si(software interrupts):软中断占用CPU的百分比
第四行表示:物理内存总量,使用中的内存总量,空闲内存总量,缓存的内存量
第五行表示:交换区内存总量,交换区使用中的内存总量,交换区空闲内存总量,交换区缓存的内存总量
二.再使用top的交互命令数字1查看每个CPU的性能数据
由于显示到CPU7,所以可以知道该服务器是一台8核的虚拟机,如果这里CPU的使用率达到了100%,则有可能出现死循环
三.使用top的交互命令H查看每个线程的性能信息
线程信息分三种情况:
1.某个线程CPU一直100%,说明该线程有可能出现死循环
2.某个线程一直再top10的位置,说明这个线程有可能有性能问题
3.CPU利用率高的几个线程在不停变化,说明不是由某一个线程导致CPU偏高
第一种情况,有可能是垃圾回收导致的,使用jstat命令查看GC情况,看看是不是持久代或年老代满了,产生FullGC,导致CPU利用率继续飙高。
方法一:jstat -gcutil pid 1000 5
方法二:把线程dump下来,查看是哪个线程、执行什么代码导致CPU利用率高
jstatck pid > ./dump
dump出来的线程ID是十六进制的,而使用top命令看到的线程ID是十进制的,需要用printf命令转换一下
printf "%x\n" pid