共计 1831 个字符,预计需要花费 5 分钟才能阅读完成。
今天断断续续的收到管理平台的异常报警,cpu 占用过高和 jvm old 占用过高,这个时候赶紧去排查原因,下面记录了我的排查过程,可能里面还有不正确的地方,欢迎各位大佬指正,也欢迎大家关于类似的案例一起交流,下面就看我关于这次排查的过程把
报警
- cpu 使用率过高报警,接近 100%
- 后续又来了 jvm old 过高报警
排查过程
- 首先打开监控平台看报警节点的 cpu 使用情况
- 登录服务器找到占用 cpu 过高线程堆栈信息
①通过 top 命令找到占用 cpu 最高的 pid[进程 id]
定位到 pid 是 1469
②通过 top -Hp pid 查看进程中占用 cpu 过高的 tid[线程 id]
③通过 printf pid |grep tid 把线程 id 转化为十六进制
④通过 jstack pid | grep tid -A 30 定位线程堆栈信息
占用 cpu 过高的线程有两个,其中一个是打印异常日志的(会 new 对象),还有 gc 线程
打印异常堆栈
这个占用 cpu 根据堆栈信息就可以定位,看下代码,可以发现 new 对象,且打印全栈信息
其中 ExceptionUtils.getFullStackTrace(e) 属于 commons.lang 包
可以发现上面两个方法会创建很多对象且打印堆栈信息占用内存
gc 线程
可以发现占用 cpu 过高的线程进行大量的 gc
- 通过 jstat -gcutil pid 时间间隔 查看 jc 信息
可以发现伊甸园区和老年代都已经满了,且进行了大量的 FGC
指标介绍
S0:年轻代第一个幸存区(survivor)使用容量占用百分比
S1:年轻代第二个幸存区(survivor)使用容量占用百分比
E:年轻代伊甸园区(eden)使用容量占用百分比
O:老年代使用容量占用百分比
P:perm 代使用容量占用百分比
YGC:从应用程序启动到当前采样时年轻代 gc 的次数
YGCT:从应用程序启动到当前采样时年轻代 gc 的时间
FGC:从应用程序启动到当前采样时老年代 gc 的次数
FGCT:从应用程序启动到当前采样时老年代 gc 的时间
GCT:从应用程序启动到当前采样时 gc 总耗时
- 导出 dump 文件,使用 jdk 自带的 jvisualvm.exe 分析
使用 jmap -dump:live,format=b,file=name.dump pid 导出 dump 文件,一般 dump 文件会比较大【我的这个 2.94G】,然后下载【可以用 sz name.dump】到本地用 jvisualvm【jdk 自带的,在 bin 目录下】分析
首先看下 dump 文件的概要
看看这些大对象都是什么
发现前面几个大对象都和 ElastaicSearchStatusException 对象有关,然后这个管理平台用到 es 的地方只有一处,就是做数据漏斗,记录广告检索在哪些步骤过滤掉,方便产品和运营查看广告被过滤的原因,然后翻开代码
其中 RestClientFactory.getRestClient().search(searchRequest) 的 search 方法一步一步跟进,发现抛 ElasticSearchStatusException 的地方
其中 parseResponseException 方法会抛出 ElasticSearchStatusException 异常,至于这两个地方具体是哪个步骤抛的,可以继续研究 es 代码判断或者 远程 debug 判定,我这里先不管了,反正我们能知道 es 出问题了
其实正是因为这里抛异常才会导致创建大量对象,因为异常在上面提到的打印异常日志的地方也会创建对象,老年代占用过高,导致大量 fgc
但 es 这里为何会有异常?
我登录到 es 的管理平台查看 es 的索引,发现有的索引没有创建,索引的创建是有任务去创建并实时写入数据的,发现那个任务已经停了。
处理过程
- 找到相关的任务重新启动,并找任务停止的原因,修复,并把丢失的索引创建并修复数据
- 在异常日志打印那最好加入流控【用 Guava.RateLimiter 控制】
小结
jvm old 区占用过高排查思路
- top 查看占用 cpu 高的进程
- jstat -gcutil pid 时间间隔 查看 gc 状况
- jmap -dump:live,format=b,file=name.dump pid 导出 dump 文件
- 用 visualVM 分析 dump 文件
cpu 占用过高排查思路
- top 查看占用 cpu 的进程 pid
- top -Hp pid 查看进程中占用 cpu 过高的线程 id tid
- printf ‘%x/n’ tid 转化为十六进制
- jstack pid |grep tid 的十六进制 -A 30 查看堆栈信息定位
欢迎关注公众号【每天晒白牙】,获取最新文章,我们一起交流,共同进步!