MySQL连接池引起的FullGC问题分析_java sigsegv com

Heap

Old Gen

图片

从上图可以发现内存中存在长时间被引用,无法被YongGC所回收的对象,并且对象大小一直在增长。直到Old Gen被堆满之后触发Full GC后对象才会回收。

临时措施

现在问题已经找到了,到目前为止只是3台实例触发了FullGC,但是在查看其它实例内存使用情况时,发现基本上所有的实例Old Gen都快到达临界点了。

所以临时解决方案是保留一台实例现场,滚动重启其它所有的实例,避免大量的实例同时进行FullGC。否则很可能导致服务雪崩。

原本服务是有设置jvm监控告警的,理论上来说当内存使用率达到一定值时会有告警通知,但是由于一次服务迁移导致告警配置失效,没有提前发现问题。

问题分析

什么对象没有被回收?

目前了解到的情况:内存无法被YoungGC回收,且无限增加,只有FullGC才能够回收这批对象

jmap -histo:live pid

图片

先简单在线上观察了一波,排第2的HashMap$Node看起来比较异常,但是看不出更详细的情况了。最好的办法还是将内存快照dump出来,使用MAT分析一波

jmap -dump:format=b,file=filename pid 

使用MAT打开之后,可以发现很明显的问题:

class com.mysql.cj.jdbc.AbandonedConnectionCleanupThread

这个类占用了80%以上的内存,那么这个类是干嘛的呢?看类名就知道,应该是MySQL Driver中用来清理过期连接的一个线程。让我们看一下源码:

图片

这个类是一个单例,会且仅会开一个线程,用来清理那些没有被显式的关闭的数据库连接。

可以看到这个类里面维护了一个Set

private static final Set<ConnectionFinalizerPhantomReference> connectionFinalizerPhantomRefs = ConcurrentHashMap.newKeySet();

对应我们上面看到的内存占用率排第二的HashMap$Node,基本上可以确定大概率是这里存在内存泄露了。在MAT上使用list_object确认一发:

图片

果然没错,罪魁祸首找到了!那么它里面存的是啥东西呢?

为什么一直增长且无法被YoungGC回收?

看名字ConnectionFinalizerPhantomReference 我们可以猜到它里面保存的应该是数据库连接的phantom引用

什么是phantom reference? 当一个对象只有phantom reference引用时,则会在虚拟机GC时被回收,同时会将phantom reference的对象放入一个referenceQueue中。

让我们来跟踪源码确认一下

图片

图片

果然是PhantomReference,里面存放的是创建的MySQL连接,看一下是在哪里被放进来的:

图片

图片

可以看到,每次创建一个新的数据库连接时,都会将创建的连接包装成PhantomReference后放入connectionFinalizerPhantomRefs中,然后这个清理线程会在一个无限循环中,获取referenceQueue中的连接并关闭

只有在 connection对象 没有其它的引用,仅存在phantom reference时,才能够被GC,并且放入referenceQueue中

为什么Connection会无限增长?

现在问题找到了,数据库连接被创建之后,则会放入connectionFinalizerPhantomRefs中,但是由于某种原因,连接前期正常使用,经过了多次minor GC都没有被回收,晋升到了老年代。但是一段时间过后,由于某种原因连接失效,导致连接池又新建了连接。

我们项目用的数据库连接池是Druid,以下为连接池配置:

图片

可以看到是设置了keepAlive,且minEvictableIdleTimeMillis设置的是5分钟,连接初始化之后,在DB请求数没有频繁的波动时,连接池应该都是维护着最小的30个连接,且会在连接空闲时间超过5分钟时进行一次keepAlive操作:

图片

图片

理论上来说,连接池是不会频繁的创建连接的,除非有活跃连接很少,且存在波动,并且keepAlive操作没有生效,在连接池进行keepAlive操作时,MySQL连接就已经失效,那么则会丢弃这个无效连接,下次再重建。

最后

由于篇幅原因,就不多做展示了
转存中…(img-DLRykwEG-1721150173385)]

[外链图片转存中…(img-0H5VH3cK-1721150173386)]

[外链图片转存中…(img-IEIMFoLG-1721150173386)]

[外链图片转存中…(img-TBP2f9yQ-1721150173387)]

由于篇幅原因,就不多做展示了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值