记录一次JVM排查

服务器 LINUX

Java 程序占用 CPU 过高排查方法:

首先找到 CPU 占用高的 Java 进程 PID,使用 top 命令;

top

之后使用 shift + p 按照 cpu 排序,查到的pid 为 80136

接下来使用 top -Hp pid ,然后使用 shift+p 按cpu排序,查找出来占用 cpu 高的线程 threadId。

top -Hp 737

之后使用 shift + p 按照 cpu 排序
查到的对应 threadId 为 741.

接下来使用 printf ‘%x\n’ threadId ,将上一步找到的 pid 转换成 16 进制;

printf ‘%x\n’ 741
输出结果为2e5

之后使用 jstack 获取线程信息 jstack PID | grep threadId

jstack 737 | grep 2e5

我们就能找到是哪个线程占用 cpu 高

1、最后使用 jstack pid(进程pid)>stack.dump 将进程堆栈打印出来

jstack 737>stack.dump

2、获取内存文件

jmap -dump:format=b,file=生成的文件名 进程号

是否频繁GC导致

jstat -gcutil 19272 2000 10

重点关注一下几列:
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
可以看到,20s 的时间中进行了 5 次 full GC,仅仅耗费在 GC 的时间已经到了 17s。

对于线上服务,如果不能开启 Debug 模式,那么可用的工具较少。推荐方式:
使用 top -c 命令查询 Java 高内存占用程序的进程 pid。然后使用 jcmd 命令获取进程中对象的计数、内存占用信息。

jcmd 24600 GC.class_histogram |head -n 10

结果中,#instances 为对象数量,#bytes 为占用内存大小,单位是 byte,class name 为对应的类名。
排名第一的是 Java 原生类型,实际上是 long 类型。

然后分析一下对应线程里面堆栈的调用关系,看看我们业务代码哪个方法使用cpu高。

最后通过:eclipse memory analyzer 分析:如下图所示

在这里插入图片描述

在这里插入图片描述

ZooKeeper#ClientCnxn#EventThread 无界队列积压了太多的任务;导致消费不过来啦;

问题原因:

因为我们是通过Elastic-job执行任务的, 在业务代码中,有很多 耗时的长任务,但是他的触发时间为 1s执行一次,但是消费跟不上。积压的任务频繁的FULL-GC、CPU高居不下;

处理方法:

通过设置 Elastic-job 的 :misfire 设置为:false(默认为true),这样就不会有短时间大量的积压任务

参数解释:

1、如果一个任务JOB的调度频率为每10s一次,在某个时间,该job执行耗时用了33s(平时只需执行5s),按照正常调度,应该后续会触发3次调度,那该job后执行完,会连续执行3次调度吗?
答案:在33s这次任务执行完成后,如果后面的任务执行在10s内执行完毕的话,只会触发一次,不会补偿3次,因为ElasticJob记录任务错失执行,只是创建了misfire节点,并不会记录错失的此时,因为也没这个必要。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值