资讯专栏INFORMATION COLUMN

Linux系统Java进程CPU高消耗问题分析

IT那活儿 / 2535人阅读
Linux系统Java进程CPU高消耗问题分析
[
概     述
]


当应用系统出现卡顿或者应用程序响应速度非常慢的时候,我们需要登录到应用所在主机进行查看、分析问题原因。


常用来排查Java进程问题命令:


  • 使用top命令查看主机资源总体使用情况,及相关Java进程占用主机资源情况;

  • 使用vmstat 2 5命令查看主机CPU、内存使用率;


  • 使用df -h命令查看主机文件系统使用率;

  • 使用netstat -na命令收集主机网络连接情况;

  • 使用pstree -p PID | wc -l查看占用CPU资源较高的进程内的线程数;

  • 使用${JAVA_HOME}/bin/jstat -gcutil PID 1000 10查看占用CPU资源较高的进程GC情况;


  • 使用${JAVA_HOME}/bin/jmap -dump:live,format=b,file=PID.hprof PID导出占用CPU资源较高的进程堆快照信息,用来统计当前JVM堆中存放了哪些对象信息;


  • 使用${JAVA_HOME}/bin/jstack PID > stack_PID.log导出占用CPU资源较高的线程栈快照信息,来最终定位占用CPU过高的代码模块。


[
常见CPU高消耗原因
]


1、大量高并发密集型计算

2、高并发的I/O读写

3、堆内存无法有效回收,FULLGC频繁

4、程序死循环

5、程序逻辑请求堵塞


[
分   析   方   法
]


案例1:Java进程耗用CPU高,但未触发FULLGC的情况

1、查看进程使用CPU、MEM情况

使用命令:top

可以看到PID为4267,USER为dform的进程CPU使用率高达1464.2%(即消耗当前主机14.64个CPU),严重超高。使用命令cat/proc/cpuinfo | grep processor |wc –l 可查看当前主机逻辑CPU个数。


2、根据问题进程的PID查询该进程的线程使用CPU、MEM情况

使用命令:top-p 4267-H

红框标出的10几个线程耗用CPU都接近或者超过了100%(即该进程下有10几个线程耗用CPU都高达1个左右)。


3、导出问题进程的线程栈信息

使用命令:

连续导出多个线程栈(stack)快照文件,每次导出间隔5s-10s

${JAVA_HOME}/bin/jstack4267 > stack_4267_1.log

${JAVA_HOME}/bin/jstack4267 > stack_4267_2.log

${JAVA_HOME}/bin/jstack4267 > stack_4267_3.log


4、将问题线程的PID(十进制)转换成十六进制的nid

使用命令:我们选取如下两个线程为例


(1)线程PID4477,转换之后的十六进制nid为117d

printf "%x "4477


(2)线程PID4542,转换之后的十六进制nid为11be


5、根据nid在第3步中导出的线程栈(stack)快照文件中查找对应的线程



(1)根据nid=0x117d查找到正在运行的程序代码模块,红框标出是该线程最后正在做的事物(线程执行顺序要从下向上看),绿框标出是应用侧代码模块。


(2)同理,根据nid=0x11be查找到正在运行的程序代码模块


最后将上述分析结果和线程栈(stack)快照文件一并反馈给应用侧核查和处理。


案例2:Java进程耗用CPU高,而且频繁触发FULLGC的情况

导致Java进程频繁FULLGC的原因有:


(1)应用代码逻辑设计不合理,对象创建太多,而且对象使用完后未及时释放资源,或者已不再有用的对象相互之间存在引用,导致该对象无法进行回收;


(2)消费者消费速度慢(或停止消费),而生产者不断往队列中投递任务,导致队列中任务累积过多,任务对象占用堆内存太多而产生FULLGC;


(3)应用进程创建线程太多(每个线程需要分配线程栈内存),也可能导致内存溢出OOM,触发FULLGC;


注:分析FULLGC的问题,除了要分析案例1中的线程栈(stack)快照信息外,还要导出JVM堆(heap)进行分析。


1、使用命令:导出JVM堆(heap)快照信息

${JAVA_HOME}/bin/jmapdump:live,format=b,file=17074.hprof17074

注:堆(heap)快照文件一般都比较大,有几个G大小(基本和参数-Xmx设置大小一致)。


2、使用Java堆分析工具MAT(MemoryAnalyzer tool)分析堆内存中对象占用情况

通过对堆内存快照文件17074.hprof的分析,发现有以下一些对象占用内存较多:


结合日志信息分析,应用一次性经过代理节点从数据节点中获取大量数据到堆内存中,并同时几条请求同时进行,该代理节点出现JVM堆内数据占用较大导致内存溢出,FULLGC无法回收,此后一直频繁FullGC。另根据GC信息分析,大约7个小时就会有一次较多请求刷新导致内存占用过多的情况。


最后将分析结果反馈给应用侧核查和处理。


[
处理建议
]


1、结合中间件侧分析结果应用侧核查对应的代码模块中是否有多线程高并发或者涉及网络间IO等,导致线程CPU耗用高的代码,并优化;


2、结合中间件侧分析结果应用侧核查相应的代码模块所涉及的业务是否存在逻辑问题,并优化;


3、对于长时间处于CPU高消耗的进程,收集完top、线程栈(stack)快照、堆(heap)快照等信息之后,可找合适时间重启该进程。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/130177.html

相关文章

  • 学点虚拟化知识

    摘要:虚拟化技术是业务发展到一定阶段,互联网企业必然会使用的技术。混部当然也有一些问题,例如同一台物理机上应用被应用突来的高峰所影响,周期被抢光,莫名其妙的负载升高。混部有时也不是一开始就能规划好的,最好能动态调整,这样就能通过虚拟化技术来做。 showImg(https://segmentfault.com/img/bVu8fH);虚拟化技术是业务发展到一定阶段,互联网企业必然会使用的技术...

    TerryCai 评论0 收藏0
  • Java多线程的一些理解

    摘要:线程仅仅被视为一个与其他进程共享某些资源的进程。稳定性可创建的线程的数量上存在限制,包括的启动参数操作系统对线程的限制,如果超出这些限制,很可能会抛出异常。若是密集型程序产生大量的线程切换,将会降低系统的吞吐量。 OS中的进程、线程 进程:即处于执行期的程序,且包含其他资源,如打开的文件、挂起的信号、内核内部数据、处理器状态、内核地址空间、一个或多个执行的线程、数据段。 线程:进程中...

    Nekron 评论0 收藏0

发表评论

0条评论

IT那活儿

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<