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工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

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

img

img

img

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

如果你觉得这些内容对你有帮助,可以扫码领取!

img

最后

分享一些系统的面试题,大家可以拿去刷一刷,准备面试涨薪。

这些面试题相对应的技术点:

  • JVM
  • MySQL
  • Mybatis
  • MongoDB
  • Redis
  • Spring
  • Spring boot
  • Spring cloud
  • Kafka
  • RabbitMQ
  • Nginx

大类就是:

  • Java基础
  • 数据结构与算法
  • 并发编程
  • 数据库
  • 设计模式
  • 微服务
  • 消息中间件

程序员,每个月给你发多少工资,你才会想老板想的事?

程序员,每个月给你发多少工资,你才会想老板想的事?

程序员,每个月给你发多少工资,你才会想老板想的事?

程序员,每个月给你发多少工资,你才会想老板想的事?

程序员,每个月给你发多少工资,你才会想老板想的事?

程序员,每个月给你发多少工资,你才会想老板想的事?

程序员,每个月给你发多少工资,你才会想老板想的事?

程序员,每个月给你发多少工资,你才会想老板想的事?

程序员,每个月给你发多少工资,你才会想老板想的事?
1711368001889)]

[外链图片转存中…(img-OgNgJkG6-1711368001890)]

[外链图片转存中…(img-599OngNj-1711368001890)]

[外链图片转存中…(img-YgGMW3ma-1711368001890)]

[外链图片转存中…(img-VJk6LNn8-1711368001890)]

[外链图片转存中…(img-LzYw3DFh-1711368001891)]

[外链图片转存中…(img-CNR0bdgd-1711368001891)]
需要更多Java资料的小伙伴可以帮忙点赞+关注,点击传送门,即可免费领取!

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐