聊聊hikari与tomcat jdbc pool的fail fast

本文主要研究在中途数据库挂的情况下,hikari与tomcat jdbc pool的fail fast情况。

实验代码

在第一次循环输出之后断开数据库连接,等个二三十秒再恢复。

hikari

从这点来看,中途数据库断开的话,hikari会不断获取数据库链接

假设数据库一直没恢复,那么所以请求数据库操作的业务线程将都阻塞connectionTimeout的时间,这个会占用工作线程

hikari只有testOnBorrow功能,是直接一个while循环,在timeout时间内不断borrow连接,validate连接,validate成功才返回或者超时抛出SQLTransientConnectionException异常。borrow的超时时间为connectionTimeout,默认30秒。

validate不成功日志记录的异常

假设在测试之前新建立好maxPoolSize的连接,那么执行之后中断数据库,则下一次的getConnection会挨个取出这些空闲连接,validate,validate失败会在log里头记录异常,同时getConnection继续循环获取连接

getConnection timeout抛出的异常

循环获取连接超时,则抛出SQLTransientConnectionException

异步线程PoolEntryCreator补充新连接在日志记录的异常

获取连接的源码

HikariCP-2.7.6-sources.jar!/com/zaxxer/hikari/pool/HikariPool.java

tomcat

tomcat jdbc pool有testOnBorrow,testOnReturn,testOnConnect,testWhileIdle属性来配置什么时候检测连接,如果是testOnBorrow的话,有空闲连接则进行borrow同时进行validate,如果上一次validate的时间在validation interval内,则默认validate成功,否则进行validate,validate失败会进行reconnect,再validate,如果再失败则抛出new SQLException(“Failed to validate a newly established connection.”)。如果没有空闲连接,且连接池没满就创建一个新的;如果没有空闲连接且连接池满了,则while轮询空闲队列,如果没取到连接,若没超过maxWait则继续,超过则抛出PoolExhaustedException。如果没有空闲连接,且连接池满了,则borrow超时时间为maxWait默认30秒。

这个示例程序,每次循环都会先归还连接再sleep,因此连接池始终有空闲连接,只是testOnBorrow校验不成功,进行了reconnect,在reconnect抛出了异常

reconnect抛出的异常

获取连接的源码

tomcat-jdbc-8.5.23-sources.jar!/org/apache/tomcat/jdbc/pool/ConnectionPool.java

小结

如果是没有空闲连接且连接池满不能新建连接的情况下

hikari则是阻塞connectionTimeout的时间,没有得到连接抛出SQLTransientConnectionException

tomcat jdbc pool会阻塞max-wait时间,若没有得到连接则抛出PoolExhaustedException

如果是有空闲连接的情况

hikari是在connectionTimeout时间内不断循环获取下一个空闲连接进行校验,校验失败继续获取下一个空闲连接,直到超时抛出SQLTransientConnectionException

tomcat jdbc pool会borrow连接然后validate连接,正常validate失败会reconnect,再validate,若此时reconnect不成功则抛出ConnectException: Connection refused,如果reconnect成功但是validate失败,则抛出SQLException(“Failed to validate a newly established connection.”)

假设数据库是挂的,但还有空闲连接,tomcat的testOnBorrow=true。对比可以发现

hikari在获取一个连接的时候,会在connectionTimeout时间内循环把空闲连接挨个validate一次,最后timeout抛出异常;之后的获取连接操作,则一直阻塞connectionTimeout时间再抛出异常

tomcat jdbc pool则是在获取一个连接的时候,先borrow出来连接,正常validate失败会reconnect,再validate,通常reconnect的时候抛出了ConnectException: Connection refused,然后业务程序会fail fast,之后的获取连接也都是fail fast的

由此可见,hikari如果connectionTimeout如果设置太大的话,在数据库挂的时候,很容易阻塞业务线程,而tomcat jdbc pool则会fail fast。

另外hikari是异步去建立minIdle大小的连接,而tomcat是同步的建立initial-size的连接。

  • 发表于:
  • 原文链接:http://kuaibao.qq.com/s/20180204G0VCI100?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券