Fast, simple, reliable. HikariCP is a "zero-overhead" production ready JDBC connection pool. At roughly 130Kb, the library is very light. Read about how we do it here.
这一段是 Hikari 的介绍,github 上的 地址,可以看到,最开始以 "Fast、simple、reliable"这三个词来介绍,“快、简单、可靠”说明了 Hikari 连接池为什么这么流行的原因。Spring Boot 2.0后默认的数据库连接池就是这个,好了,废话不多说,下面就来看看在使用中遇到的问题。
问题的起源
现在在用的项目由本人新建,新建不久后发现程序一启动完之后,就会报数据库连接池泄漏,开始以为设置的检查连接泄漏时间太短了,下面是连接池的配置:

然后把 leakDetectionThreshold 设置成 5000 毫秒,之前是 2000,然后发现消停了一段时间,确实没报 java.lang.Exception: Apparent connection leak detected这个异常了,但是后面不管执行一个什么操作还是会报连接泄漏。当时项目进度比较紧,这个错误又不影响使用,只是看日志的时候感觉程序出错了,所以一直拖到现在才来解决。
现象
以当时解决问题的思路,觉得把检测连接时间再设置大一点就行了,但是仔细一想,问题并没有想像中的那么简单,然后仔细跟了一下报错的类,发现是 Spring 中 Quartz 相关的类报出来的错:

因为项目中用了定时任务,所以会有Quartz相关的类,既然错误出来了,跟进去看一看。,这里报错的是 nonTxDataSourceToUse.getConnection() 方法,在拿连接时报了错,这里会返回一个没有事务的连接,住下跟就是具体的实现了。

因为我用的是 Hikari 连接池,所以选择 Hikari 相关的类跟进去。

这里找到取连接的方法 getConnection() 再继续往下看:

上面两个返回的都是一样的对象,只不过多了一次判断,看是否已经New了连接池,这个 getConnection() 方法里面就是真正创建连接池的方法,这里看红框里面这个代码,会生成一个代理连接类,然后传入了一个代理泄漏检查任务类,下面来看这个类里面干了什么。

这个任务类里面首先会判断,检查连接泄漏是否有值,如果有值的话,就创建了一个定时的线程池,如果没有值,就创建一个空的 ProxyLeakTash 对象。这个对象里面只干一件事情,就是启动定时线程池去检测是否超过设置的时间,单位是毫秒,如果超过就报异常,所以把检测连接泄漏时间设置大一点也是有依据的。在打印异常之前,会把最后红框那个 warn 日志打印出来。

方案
在调大了 leakDetectionThreshold 这个值之后(从2000调到5000),再运行Job好像还是会报这个错误,在跟进了上面的源代码之后,可以选择再次调大这个数值。但是如果在调试阶段,断点时间一长,又会报这个错。好在不太影响程序正常运行,现在选择是把数值再次调大,后续再深入 Hikari 创建连接池连接的问题。
本文介绍了在Java项目中遇到Hikari连接池泄漏的问题,详细分析了问题的起源,发现即使增加leakDetectionThreshold值,问题依然存在。通过跟踪代码,定位到Spring Quartz定时任务与Hikari连接池的交互,揭示了连接泄漏检查的实现原理。最后提出了暂时增大leakDetectionThreshold的解决方案,并计划进一步研究Hikari创建连接池的过程,以彻底解决连接泄漏问题。

1821

被折叠的 条评论
为什么被折叠?



