cpu使用率_cpu 使用率过高和 jvm old 占用过高排查过程

a9f4dc15d7a212fecfd51d1d144100e9.gif

精品专栏

 
  • 死磕 Java 并发

  • 死磕 Sharding-jdbc

  • 死磕 Spring 之 IOC

12884aea34159602a7fa08a40377793e.png

今天断断续续的收到管理平台的异常报警,cpu占用过高和jvm old占用过高,这个时候赶紧去排查原因,下面记录了我的排查过程,可能里面还有不正确的地方,欢迎各位大佬指正,也欢迎大家关于类似的案例一起交流,下面就看我关于这次排查的过程把

报警

  1. cpu使用率过高报警,接近100%

  2. 后续又来了jvm old过高报警

排查过程

  1. 首先打开监控平台看报警节点的cpu使用情况

f454544a050364328dee1ecaea79d449.png

  1. 登录服务器找到占用 cpu过高线程堆栈信息

①通过 top 命令找到占用cpu最高的 pid[进程id]

16acc201ce3d250467b856422f084515.png

定位到pid是 1469

②通过 top -Hp pid 查看进程中占用cpu过高的 tid[线程id]

③通过 printf  pid |grep tid 把线程id转化为十六进制

④通过 jstack pid | grep tid -A 30 定位线程堆栈信息

占用cpu过高的线程有两个,其中一个是打印异常日志的(会new 对象),还有gc线程

打印异常堆栈

b5b9774594cce35a9e42c6545d76ee83.png

这个占用cpu根据堆栈信息就可以定位,看下代码,可以发现new 对象,且打印全栈信息

ad8144b6e52b5a182631f914c864a44a.png

其中ExceptionUtils.getFullStackTrace(e) 属于commons.lang包

57a456ce28793408c68bced2b7438a1e.png

可以发现上面两个方法会创建很多对象且打印堆栈信息占用内存

gc线程

9075861146cec0df90e530d7caaa8a75.png

可以发现占用cpu过高的线程进行大量的gc

  1. 通过 jstat -gcutil pid 时间间隔 查看 jc  信息

809dcc98e8327cdcc44a57efbc38e556.png

可以发现伊甸园区和老年代都已经满了,且进行了大量的FGC

指标介绍

S0:年轻代第一个幸存区(survivor)使用容量占用百分比

S1:年轻代第二个幸存区(survivor)使用容量占用百分比

E:年轻代伊甸园区(eden)使用容量占用百分比

O:老年代使用容量占用百分比

P:perm代使用容量占用百分比

YGC:从应用程序启动到当前采样时年轻代gc的次数

YGCT:从应用程序启动到当前采样时年轻代gc的时间

FGC:从应用程序启动到当前采样时老年代gc的次数

FGCT:从应用程序启动到当前采样时老年代gc的时间

GCT:从应用程序启动到当前采样时gc总耗时

  1. 导出dump文件,使用jdk自带的jvisualvm.exe分析

使用 jmap -dump:format=b,file=name.dump pid 导出dump文件,一般dump文件会比较大【我的这个2.94G】,然后下载【可以用 sz name.dump】到本地用jvisualvm【jdk自带的,在bin目录下】分析

首先看下dump文件的概要

7a535502d37387094dbe223b7c2a2429.png

看看这些大对象都是什么

1ef96a283866f5d74fc242220b953852.png

发现前面几个大对象都和 ElastaicSearchStatusException对象有关,然后这个管理平台用到es的地方只有一处,就是做数据漏斗,记录广告检索在哪些步骤过滤掉,方便产品和运营查看广告被过滤的原因,然后翻开代码

df575c393aa492b159f3a60c90f38e74.png

其中 RestClientFactory.getRestClient().search(searchRequest)的 search方法一步一步跟进,发现抛ElasticSearchStatusException的地方

de6e3a8055c9ddefc32a7103338624ce.png

其中parseResponseException方法会抛出ElasticSearchStatusException异常,至于这两个地方具体是哪个步骤抛的,可以继续研究es代码判断或者 远程debug判定,我这里先不管了,反正我们能知道es出问题了

其实正是因为这里抛异常才会导致创建大量对象,因为异常在上面提到的打印异常日志的地方也会创建对象,老年代占用过高,导致大量fgc

但es这里为何会有异常?

我登录到es的管理平台查看es的索引,发现有的索引没有创建,索引的创建是有任务去创建并实时写入数据的,发现那个任务已经停了。

处理过程

  1. 找到相关的任务重新启动,并找任务停止的原因,修复,并把丢失的索引创建并修复数据

  2. 在异常日志打印那最好加入流控【用Guava.RateLimiter控制】

小结

cpu占用过高排查思路

  1. top 查看占用cpu的进程 pid

  2. top -Hp pid 查看进程中占用cpu过高的线程id  tid

  3. printf '%x/n' tid 转化为十六进制

  4. jstack pid |grep tid的十六进制 -A 30 查看堆栈信息定位

jvm old区占用过高排查思路

  1. top查看占用cpu高的进程

  2. jstat -gcutil pid 时间间隔 查看gc状况

  3. jmap -dump:format=b,file=name.dump pid  导出dump文件

  4. 用visualVM分析dump文件

往期精彩

阿里面试题:如何保证缓存与数据库的双写一致性?

一篇超实用的服务异常处理指南

如何设计一个完美的权限管理模块

一个经典面试题:如何保证缓存与数据库的双写一致性?

分享一道阿里Java并发面试题 (详细分析篇)

为什么 Redis 单线程却能支撑高并发?

聊一聊 Spring 中的线程安全性

为什么你的Intellij没别人的好用?

面试官:不使用synchronized和lock,如何实现一个线程安全的单例?

你必须要知道的锁原理、锁优化、CAS、AQS

你真的理解零拷贝吗?

END 75dd3e9be0b4d6c7082fc10175e48332.png

>>>>>> 加群交流技术 <<<<<<

f6553b1961bda4979847e48e585f70bd.png 你点的每个“在看”,我都认真当成了喜欢
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值