出现OOM问题后, 我们如何排查问题的出现点呢? 在这篇博客中我只是简单的说下如何排查问题的。

找到问题进程ID

第一步都是确定你的服务的进程id,有两种linux指令使用,

top命令

使用top -c 会列出当前的进程列表:
在这里插入图片描述
如果你的应用出现问题,cpu占用很高, 内存占用也很高的话, 你的进程就会排在很前面。 在图中列表的第一列就是进程的id

关于其中的图中各个参数的意义 可以参考: https://blog.csdn.net/yjclsx/article/details/81508455

ps 命令

如果你知道的是哪个进程, 只是不知道哪个pid , 这个命令可以帮助你。
ps -ef| grep 'java'
在这里插入图片描述
这个命令中的 grep 后面可以使用你的项目关键字查找你的项目。

在列出来的信息中,第二列代表的就是相关的进程id

查看GC情况

jstat -gc 1
在这里插入图片描述

由于我是进入docker 容器中执行的top命令, 所以我的java的进程id是1

其中参数简单说明下:
S0C:第一个幸存区的大小
S1C:第二个幸存区的大小
S0U:第一个幸存区的使用大小
S1U:第二个幸存区的使用大小
EC:伊甸园区的大小
EU:伊甸园区的使用大小
OC:老年代大小
OU:老年代使用大小
MC:方法区大小
MU:方法区使用大小
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间

对于应用先不要急着把堆栈信息Dump下来, 因为有时候Jstat也能发现一部分问题, 我的上次有个预发环境的OOM问题就是由于老年代和新生代的大小分配有问题导致的。 并且有时候线上的不一定配置了-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.hprof 需要运维帮你jmap下来堆栈日志。

一般出现OOM的情况, 应用会频繁的进行GC活动的, 这里也可以看下GC的次数和时间也大概能知道是不是出现问题了

查看Jstack 查看栈信息

如果你的应用cpu占用100%导致变卡顿了, 但是堆栈并没有溢出, 此时你可以通过这个命令让控制台打印栈日志, 查看线程的情况。 通过这个jstack 就能排查出来99%死循环和死锁的等待线程方面的问题。

在这里插入图片描述

如果项目中出现CPU百分百的情况, 你需要的是找出这个线程, 使用top -Hp 1 -c 命令会列出进程1 下的所有线程:
在这里插入图片描述
注意此时图中的PID表示的是线程id, 我们需要把线程id转换成16进制的格式, 图中第一个线程的id是33, 将其转换成16进制后变成 0x21

这个时候我们使用 jstack -l 1 | grep 0x21 查看下这个线程的栈信息,
在这里插入图片描述
抱歉我选了一个很不直观的例子, 所以我在网上找了个图片
在这里插入图片描述
这个图片中线程0x1be8 是在RUNNABLE状态中,并且明显的是在com.hp.ccue.ideneity.web.api.aspect.logs.TaskExecuter.run 这个方法运行中, 那我我们就要看下源码中这个方法是否有导致死循环的坑了。

dump出jvm的堆栈文件

如果通过上面的操作你还是无法缺点问题的所在,这个时候你需要的就是堆栈文件了, 如果你没有出问题机器的权限, 就找运维吧。

如果你有权限,那么恭喜你,jmap -dump:format=b,file=fileName.hprof 1 命令把堆栈文件dump下来, 这个命令中 1 就是你的进程id。 fileName就是你的自定义的堆栈文件的名称, 后缀是hprof

这个文件还需要你借助工具分析, 下面我推荐MAT工具,下载地址:https://www.eclipse.org/mat/downloads.php

MAT工具使用

堆栈文件旺旺会很大, 但是MAT只默认支持1g内的堆栈分析, 这个时候你需要修改下启动配置参数
Mac电脑: /Applications/mat.app/Contents/Eclipse/MemoryAnalyzer.ini 这里改下Xmx的大小大于1G。 在这里插入图片描述
WIN电脑可以百度下怎么修改配置。

此时一个大内存的电脑的重要性就提现出来了

在这里插入图片描述
选择你之前Dump下来的文件, 打开它。
在这里插入图片描述
在这里插入图片描述
图中的饼图列出来占用最大三个类的对象的大小,点击图中的Leak Suspects 选项后
在这里插入图片描述
仔细看看它给你列举出来的可能的问题, 找找也没有你业务代码中的问题, 图中三个问题其实都是Spring框架或者Apache的框架类中的问题, 是MAT分析的坑的问题。

通过这分析, 你大概率能够发现你的代码问题的。

jvm的监控

下面只是简单的介绍,关于详细的对接使用信息, 我会在后面的博客中单开一篇说面的。

使用prometheus + Grafana 可以实现下图所示的酷炫监控页面。
在这里插入图片描述
我们在springboot项目中需要引入:

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>io.micrometer</groupId>
			<artifactId>micrometer-registry-prometheus</artifactId>
			<version>1.1.3</version>
		</dependency>

配置正确就有基本的jvm监控了。

prometheus

一个时序数据库,我们的监控数据可以很方便的实时上报到这个数据库中。
Springboot项目中接入micrometer-registry-prometheus, 那么基本的jvm信息就自动上报到prometheus了。 同样我们也可以自定义上报业务信息,从而监控系统的业务执行状态。

这个数据库还提供了很多的插件, 可以通过插件可以很方便的监控linux的情况, mysql情况等等, 十分方便。

Grafana

一个多功能的图表展示工具, 结合prometheus可以自定义展示酷炫的图表信息。
在这里插入图片描述

Logo

更多推荐