Druid版本

  1. <dependency>
  2. <groupId>com.alibaba</groupId>
  3. <artifactId>druid</artifactId>
  4. <version>1.0.16</version>
  5. </dependency>

现象 😣

早上起来看到告警群中全部都是项目的FullGC告警,其中还夹杂着部分OOM的告警. 甚至还有2台Tomcat没有上线也存在这个情况.

说明不是外部请求导致的. 且该项目后台启动了一个线程用于消费消息队列.

处理问题 🌲

看实例对象

image.png
有问题,但是看不出来啥.

看堆栈

使用
jstack 生成对堆栈进行分析,一无所获. 处于 Runnable 中的线程寥寥无几.. 根据不包含这个数据

dump 😂

命令 jmap -dump:live,format=b,file=pid.hprof pid

使用 mat 打开dump文件,可以直观的看到
image.png
看是否是瞬时流量导致OOM,操作IncomingOutcoming ,没有找到,确定是内存泄露导致的内存溢出。

2020-12-28补充 这里我陷入了一个误区(或者是一个长久以来错误的认知), 我错误的认为这个是在查询的过程中撑爆了内存(这个有可能,但是我以为大部分是这样,就犯错了)。 其实内存泄漏是一个缓慢进行的过程,并不是一蹴而就的. 所以只要找到最大的堆积即可,不要太固执的去找所谓的堆栈…

换成 JProfiler 试试 (刚下载把玩,感觉和mat差不多,界面美观不少)

打开dump下来对hprof文件. 和MAT显示的差不多.
image.png
com.alibaba.druid.stata.JdbcDataSourceStat$1 这个竟然包含了这么多,有经验的开发者都知道 $1 是类内部的一个实例类. 举个例子.

源文件

image.png

编译后的class文件…

image.png

打开 idea 开始看这个类.
image.png
在看是在哪里 put 数据的
image.png
到这里基本上就明白了,是因为配置 DataSource 的时候 Filter 配置了 stat 参数. 快速去掉发布上线.

第二天一看,稳的一批..

总结

看这个dump文件是比较难受,尤其是我的思考方向错误的时候. 很想知道根据这个对象来找到它的堆栈入口,各种点,结果根本就没有,这里还是思考🤔方向错误了. 下次就不会如此了.

这个Filter是用于界面看数据使用的,如果我们不看或者是有其他途径看sql,其实是可以关闭的.

思考

在什么情况下 sqlStatMap 会把数据给清空呢? 当时又是源于什么情况导致Map堆积了这么多的数据呢?

事后链接