linux排查CPU或内存占用高问题(JAVA程序导致linux服务器CPU过高和内存过高)
最近生产环境经常发生CPU和内存异过高的情况,以前一般排查的也是一些死锁问题,排查死锁的时候直接打印程序的堆栈信息,然后查看线程的各种状态,差不多都能猜到问题所在,这两天cpu和内存问题刚开始也是直接打印堆栈信息,然后发现堆栈信息太多,很难定位到是什么导致了cpu和内存问题,虽然在堆栈文件里面找到很多自己写的业务代码,但是因为执行的线程比较多,查询起来比较费劲(基本上来说除非交易量很大,应用支持不了需要扩容,大部分的问题都是我们自己写的业务代码导致的。),网上对这些排查的方式也比较多了,这里记录一下自己的操作记录,生产环境我们也操作不了,我们提供操作方法,其他的就给运维去处理 了。
参考链接:这类问题还是比较成熟的,网上方案也很多,自己动手做一遍才能记住。
https://blog.csdn.net/notsaltedfish/article/details/80209538
https://blog.csdn.net/xgjianstart/article/details/53427420
https://blog.csdn.net/qq_24949727/article/details/70738723
https://www.iteye.com/blog/host-2365495
https://blog.csdn.net/daiyudong2020/article/details/52760846
https://www.cnblogs.com/lixiuyuan999/p/6384167.html
第一步:找出最占线程和CPU的进程
既然是CPU和内存高导致的问题,那么第一步肯定是找出占CPU和线程最高的进程了
命令
- 执行top命令
- 按P(注意是大写的P,直接按shift+p也可以)–>以 CPU 占用率大小的顺序排列进程列表
- 按M(注意是大写的M,直接按shift+m也可以) --> 以内存占用率大小的顺序排列进程列表
- 图中的第一列PID,就是占用的进程ID,这里是进程不是线程,后面都会用到这个进程ID的。
第二步:定位到哪个服务(这一步不需要,我只是想知道是哪个应用占用的CPU和内存)
这里执行命令中的4863就是第一步中获取到的PID。
[aaa@qq.com ~]$ ps -ef |grep 4863
第三步:先打印堆栈信息
执行jstack 16799 > dump
,把堆栈信息输出到文本文件里面,方便后面查找,图中的命令指示为了方便演示,我们以前定位死锁的时候基本就是把堆栈信息打印就结束了,问题就是你会发现这个堆栈文件很长,要一个一个的查看,看的头疼,所以我们只需要看我们需要看的就行了,我们需要看占CPU或内存高的线程的堆栈就行了。
第四步:通过进程找出最占CPU或内存的线程
应用程序占用CPU或内存的都是线程在执行,所以关键点是找到线程的堆栈。
命令格式top -Hp pid |grep -v pid
这里的pid还是最上面通过top找出来的pid,后面添加grep -v只是排除进程自身的线程(这句话貌似不准确)。
命令操作步骤
- 执行top -Hp pid |grep -v pid命令
- 按P(注意是大写的P,直接按shift+p也可以)–>以 CPU 占用率大小的顺序排列进程列表
- 按M(注意是大写的M,直接按shift+m也可以) --> 以内存占用率大小的顺序排列进程列表
- 图中的第一列PID,是上面这个进程的线程ID,这里是名字虽然显示PID,其实我们找出来是线程ID,就是我们所说的tid
[aaa@qq.com ~]$ top -Hp 4196 |grep -v 4196
第五步:把第四步找到的线程ID转换成16进制,默认显示的10进制。
执行 printf ‘%x\n’ 4199来进行转换,这里的4199就是上面的PID(我们一般叫做TID,因为这里显示的线程号)
[aaa@qq.com ~]$ printf '%x\n' 4249
1099
[aaa@qq.com ~]$ printf '%x\n' 4199
1067
[aaa@qq.com ~]$
第六步:就是根据转换之后的PID到堆栈信息里面查找了。
使用转换成16进制的数字去堆栈信息里面找,可以直接使[aaa@qq.com ~]$ jstack 4863 |grep -10ab 1309
命令去查看,最好还是把堆栈文件打印出来,然后用vi进去,使用查找命令进行查看。
总结
生产上出CUP和内存问题,基本上都是按照这个思路去找的,但是找到了之后还需要分析代码的,常规思路CPU过高一般是计算型任务执行很久,比如说SQL写的不好查询不出来呀,内存问题就是大量new对象或者读取大文件,尤其在上传execl表格的时候,其次就是注意查询东西,返回东西的时候一般要控制好返回的数量,不要一次性查询出来然后通过网络返回,这种操作在并发稍微大一点的时候就会出现各种问题,一台机器上,一个应用程序的问题可能引起整台服务器的其他应用都会出现问题。