赞
踩
对于互联网公司,线上CPU飙升的问题很常见(例如某个活动开始,流量突然飙升时),按照本文的步骤排查,基本1分钟即可搞定!特此整理排查方法一篇,供大家参考讨论提高。
线上系统突然运行缓慢,CPU飙升,甚至到100%,以及Full GC次数过多,接着就是各种报警:例如接口超时报警等。此时急需快速线上排查问题。
不管什么问题,既然是CPU飙升,肯定是查一下耗CPU的线程,然后看看GC。
Java 内存不够或者溢出导致GC overhead limit exceeded。
代码中互相竞争导致的死锁。
特别耗费计算资源的操作,比如正则匹配,Java中的正则匹配默认有回溯问题,复杂的正则匹配引起的CPU异常。
死循环引起的CPU高度密集计算。
针对第1种,根据Oracle官方资料,GC overhead limit exceeded表示JVM一直在GC导致应用程序变慢,具体量化指标就是JVM执行垃圾回收花费超过98%的时间,但释放出的可用堆内存却少于2%,连续多次(一般5次)GC回收的内存都不足2%的情况下就会抛出此异常。
经过垃圾回收每次释放的内存都少于2%很容易又被新生对象填满,JVM快速进入下一次垃圾回收,无限循环,由此引起频繁的GC长期消耗我们服务器CPU资源,从而使CPU使用率达到100%
我们可以使用-XX:-UseGCOverheadLimit这个参数关闭GC overhead limit exceeded,但这样治标不治本,建议检查应用程序的内存使用是否合理以及是否需要增加堆内存。
TOP命令找到占用CPU高的Java进程PID
top
根据进程ID找到占用CPU高的线程
ps -mp pid -o THREAD,tid | sort -r
将指定的线程ID输出为16进制格式
printf “%x\n” tid
根据16进制格式的线程ID查找线程堆栈信息
jstack pid |grep tid -A 50
获取到线程堆栈信息就好办了,以上即是采用单线程模拟一个复杂的正则匹配的堆栈示例图,可以看得出线程都在指向regex.Pattern,在生产多线程环境下这个复杂正则匹配会导致CPU利用率奇高。
负载总结为一句话就是:需要运行处理但又必须等待队列前的进程处理完成的进程个数。具体来说,也就是如下两种情况:
等待被授权予 CPU 运行权限的进程、等待磁盘 I/O 完成的进程。
CPU 低而负载高也就是说等待磁盘 I/O 完成的进程过多,就会导致队列长度过大,这样就体现到负载过大了,但实际是此时 CPU 被分配去执行别的任务或空闲,具体场景有如下几种:
top -p pid
针对所要查的 pid 查看该进程的 CPU 和内存以及负载情况。jmap -histo:live [pid]
,然后分析具体的对象数目和占用内存大小,从而定位代码。jmap -dump:live,format=b,file=xxx.xxx [pid]
,然后利用 MAT 工具分析是否存在内存泄漏等等。赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。