序
本文主要研究在中途数据库挂的情况下,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的连接。
领取专属 10元无门槛券
私享最新 技术干货