我有一个 Spring Boot (v2.0.8) 应用程序,它使用 HikariCP (v2.7.9) 池(连接到 MariaDB),配置如下:
minimumIdle: 1
maximumPoolSize: 10
leakDetectionThreshold: 30000
问题是我们的生产组件每隔几周就会重复抛出SQLTransientConnectionException“连接不可用,请求在 30000 毫秒后超时...”
。问题是它永远不会从中恢复并始终抛出异常。因此需要重新启动组件。
从 HikariPool 源代码来看,似乎发生了这种情况,因为每次调用 connectionBag.borrow(timeout, MILLISECONDS)
时,poolEntry 都是 null,因此会抛出超时异常。要使其为空,连接池必须没有空闲条目,即sharedList中的所有PoolEntry都被标记为IN_USE
。
我不确定为什么组件无法从中恢复,因为最终我希望 PoolEntry 被标记为 NOT_IN_USE
并且这会打破重复的异常。
我能想到的可能场景:
所有条目均处于
IN_USE
状态,并且数据库暂时关闭。我希望飞行中的查询会抛出异常。也许此时 PoolEntry 状态永远不会重置,因此停留在IN_USE
状态。在这种情况下,我会认为如果抛出异常,状态就会改变,以便可以从池中清除连接。谁能确认一下情况是否如此?向组件发出大量 REST 请求,而这些请求又需要执行数据库查询。这会填满连接池,因此后续请求会超时等待先前的请求完成。这是有道理的,但我希望组件在请求完成后恢复,但事实并非如此。
有人知道这里可能出现什么问题吗?我尝试过配置 Hikari 文档中的各种超时,但没有成功诊断/解决此问题。任何帮助将不胜感激。
谢谢!
最佳答案
场景 2 最有可能发生。当我将其与云数据流一起使用并收到大量连接请求时,我遇到了同样的问题。我找到的唯一解决方案是使用配置来找到适合我的用例的组合。
我将给您留下我的代码,该代码适用于每秒 50-100 个请求,祝您好运。
private static DataSource pool;
final HikariConfig config = new HikariConfig();
config.setMinimumIdle(5);
config.setMaximumPoolSize(50);
config.setConnectionTimeout(10000);
config.setIdleTimeout(600000);
config.setMaxLifetime(1800000);
config.setJdbcUrl(JDBC_URL);
config.setUsername(JDBC_USER);
config.setPassword(JDBC_PASS);
pool = new HikariDataSource(config);
关于java - HikariCP 连接超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56569495/