HikariPool-1 - Connection is not available, request timed out after 6000ms

Caused by: java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 6000ms.

at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:695)

at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:197)

at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:162)

at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:128)

at org.springframework.jdbc.datasource.DataSourceUtils.fetchConnection(DataSourceUtils.java:158)

at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:116)

at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:79)

… 75 more

百度了一下,很多都说需要把spring.datasource.hikari.connection-timeout的值调大就行。但是我们试了一下之后发现效果并不明显,然后我们调大了spring.datasource.hikari.maximum-pool-size的大小,这下有效果了。这是为什么呢?

排查

==================================================================

一直以来,我都以为这个报错是hikari连接数据库时,创建数据库连接超时抛出的异常,但是翻了一下抛出异常的源码之后发现并不是这样的,简单的贴一下代码:

public Connection getConnection(final long hardTimeout) throws SQLException

{

suspendResumeLock.acquire();

final long startTime = currentTime();

try {

long timeout = hardTimeout;

do {

PoolEntry poolEntry = connectionBag.borrow(timeout, MILLISECONDS);

if (poolEntry == null) {

break; // We timed out… break and throw exception

}

final long now = currentTime();

if (poolEntry.isMarkedEvicted() || (elapsedMillis(poolEntry.lastAccessed, now) > aliveBypassWindowMs && !isConnectionAlive(poolEntry.connection))) {

closeConnection(poolEntry, poolEntry.isMarkedEvicted() ? EVICTED_CONNECTION_MESSAGE : DEAD_CONNECTION_MESSAGE);

timeout = hardTimeout - elapsedMillis(startTime);

}

else {

metricsTracker.recordBorrowStats(poolEntry, startTime);

return poolEntry.createProxyConnection(leakTaskFactory.schedule(poolEntry), now);

}

} while (timeout > 0L);

metricsTracker.recordBorrowTimeoutStats(startTime);

throw createTimeoutException(startTime);

}

catch (InterruptedException e) {

Thread.currentThread().interrupt();

throw new SQLException(poolName + " - Interrupted during connection acquisition", e);

}

finally {

suspendResumeLock.release();

}

}

里面的代码虽然没有细究,但是从意思上看,应该是如果在hardTimeout时间内没有从连接池中获取到有效的连接,那就抛出异常,而抛出的正是日志中大量打印的那个异常。

论证

==================================================================

从上面的源码中看,增加spring.datasource.hikari.connection-timeout的值应该确实是有效的,最起码可以降低异常率,但是总连接数依然不足,所以看起来的现象应该是日志中的报错少了,但是系统会卡的要命。增加spring.datasource.hikari.maximum-pool-size之后整个系统可用的最大连接数变多了,自然就不卡不报错了。

通过demo重现问题

==========================================================================

为了验证我的想法,我写了一个demo

数据库相关配置文件:

#5个最小空闲连接,我把它理解为coreSize

spring.datasource.hikari.minimum-idle=5

#最大生命周期60s,测试用

spring.datasource.hikari.max-lifetime=60000

#一个连接空闲10s后,将会被回收

spring.datasource.hikari.idle-timeout=10

#连接池中的最大连接数

spring.datasource.hikari.maximum-pool-size=10

#获取连接的等待时长5s

spring.datasource.hikari.connection-timeout=5000

#判断连接是否有效

spring.datasource.hikari.connection-test-query=select 1

demo源码:

@SpringBootApplication(scanBasePackages = “com.example.juc.hikari”)

public class Main {

private static final Logger logger = LoggerFactory.getLogger(Main.class);

public static void main(String[] args) {

ConfigurableApplicationContext applicationContext = SpringApplication.run(Main.class, args);

DataSource dataSource = applicationContext.getBean(DataSource.class);

logger.info(“{}”, dataSource);

//先获取10个连接,就获取,不释放

int maxConnectionCount = 10;

List connections = new ArrayList<>();

for (int i = 0; i < maxConnectionCount; i++) {

try {

Connection connection = dataSource.getConnection();

connections.add(connection);

} catch (SQLException e) {

e.printStackTrace();

}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

由于篇幅有限,这里就不一一罗列了,20道常见面试题(含答案)+21条MySQL性能调优经验小编已整理成Word文档或PDF文档

MySQL全家桶笔记

还有更多面试复习笔记分享如下

Java架构专题面试复习

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
Word文档或PDF文档

[外链图片转存中…(img-Q8Do01Kr-1712576277036)]

还有更多面试复习笔记分享如下

[外链图片转存中…(img-nJ8uWizZ-1712576277036)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 22
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值