【追光者系列】HikariCP 源码分析之从 validationTimeout 来讲讲 2.7.5 版本的那些故事
摘要: 原文可阅读 http://www.iocoder.cn/HikariCP/zhazhawangzi/validationTimeout 「渣渣王子」欢迎转载,保留摘要,谢谢!
- 概念
- 源码解析
-
Write
- #PoolBase
- #HouseKeeper
-
Read
- #getConnection
- #newConnection
- Hikari 2.7.5的故事
- 两个关键的Mbean
- 2.7.5迎来了不可变设计
- 且看大神论道
img
今晚给大家讲一个故事,如上图所示,Hikari作者brettwooldridge先生非常无奈的在issue里回复了一句“阿门,兄弟”,到底发生了什么有趣的故事呢?这是一篇风格不同于以往的文章,就让我来带大家从源码validationTimeout分析角度一起揭开这个故事的面纱吧~
概念
此属性控制连接测试活动的最长时间。这个值必须小于connectionTimeout。最低可接受的验证超时时间为250 ms。 默认值:5000。
validationTimeout This property controls the maximum amount of time that a connection will be tested for aliveness. This value must be less than the connectionTimeout. Lowest acceptable validation timeout is 250 ms. Default: 5000
更多配置大纲详见文章 《【追光者系列】HikariCP默认配置》
img
源码解析
我们首先来看一下validationTimeout用在了哪里的纲要图:
img
Write
我们可以看到在两处看到validationTimeout的写入,一处是PoolBase构造函数,另一处是HouseKeeper线程。
PoolBase
在com.zaxxer.hikari.pool.PoolBase中的构造函数声明了validationTimeout的初始值,而该值真正来自于com.zaxxer.hikari.HikariConfig的Default constructor,默认值为
但是在HikariConfig的set方法中又做了处理
这就是概念一栏所说的 如果小于250毫秒,则会被重置回5秒 的原因。
HouseKeeper
我们再来看一下com.zaxxer.hikari.pool.HikariPool这个代码,该线程尝试在池中维护的最小空闲连接数,并不断刷新的通过MBean调整的connectionTimeout和validationTimeout等值。 HikariCP有除了这个HouseKeeper线程之外,还有新建连接和关闭连接的线程。
Read
getConnection
在com.zaxxer.hikari.pool.HikariPool的核心方法getConnection中用到了validationTimeout,我们看一下源码, borrow 到poolEntry之后,如果不是isMarkedEvicted,则会调用isConnectionAlive来判断连接的有效性,再强调一下 hikari是在borrow连接的时候校验连接的有效性 :
我们具体来看一下isConnectionAlive的实现:
从如下代码可以看到,validationTimeout的默认值是5000毫秒,所以默认情况下validationSeconds的值应该在1-5毫秒之间,又由于validationTimeout的值必须小于connectionTimeout(默认值30000毫秒,如果小于250毫秒,则被重置回30秒),所以默认情况下,调整validationTimeout却不调整connectionTimeout情况下,validationSeconds的默认峰值应该是30毫秒。
如果是jdbc4的话,如果使用isUseJdbc4Validation(就是config.getConnectionTestQuery() == null的时候)
用connection.isValid(validationSeconds)来验证连接的有效性,否则的话则用connectionTestQuery查询语句来查询验证。这里说一下java.sql.Connection的isValid()和isClosed()的区别:
isValid:如果连接尚未关闭并且仍然有效,则返回 true。驱动程序将提交一个关于该连接的查询,或者使用其他某种能确切验证在调用此方法时连接是否仍然有效的机制。由驱动程序提交的用来验证该连接的查询将在当前事务的上下文中执行。 参数:timeout - 等待用来验证连接是否完成的数据库操作的时间,以秒为单位。如果在操作完成之前超时期满,则此方法返回 false。0 值表示不对数据库操作应用超时值。 返回:如果连接有效,则返回 true,否则返回 false
isClosed:查询此 Connection 对象是否已经被关闭。如果在连接上调用了 close 方法或者发生某些严重的错误,则连接被关闭。只有在调用了Connection.close 方法之后被调用时,此方法才保证返回true。通常不能调用此方法确定到数据库的连接是有效的还是无效的。通过捕获在试图进行某一操作时可能抛出的异常,典型的客户端可以确定某一连接是无效的。 返回:如果此 Connection 对象是关闭的,则返回 true;如果它仍然处于打开状态,则返回 false。
newConnection
在com.zaxxer.hikari.pool.PoolBase的newConnection#setupConnection()中,对于validationTimeout超时时间也做了getAndSetNetworkTimeout等的处理
Hikari 2.7.5的故事
从validationTimeout我们刚才讲到了有一个HouseKeeper线程干着不断刷新的通过MBean调整的connectionTimeout和validationTimeout等值的事情。这就是2.7.4到2.7.5版本的一个很重要的改变,为什么这么说?
两个关键的Mbean
首先Hikari有两个Mbean,分别是HikariPoolMXBean和HikariConfigMXBean,我们看一下代码,这两个代码的功能不言而喻: