数据库故障后的 Hikari CP (Spring Boot) 连接恢复问题

Posted

技术标签:

【中文标题】数据库故障后的 Hikari CP (Spring Boot) 连接恢复问题【英文标题】:Hikari CP (Spring Boot) Connection Recovery Problem After DB Failure 【发布时间】:2021-12-02 13:49:57 【问题描述】:

我们在 Spring Boot (2.2.4) 和 Hikari CP (3.4.2) 上使用 PostgreSQL 构建了多个微服务。

最近我们遇到了大约 30 秒的数据库故障。连接丢失后,一些容器无法恢复连接,而其他具有完全相同配置和应用程序的容器就可以了。不幸的是,我们没有在错误发生时指示池大小(空闲活动等待)的日志。

当连接丢失时,我们在所有容器上都收到了一些损坏的管道和连接丢失错误。数据库恢复后,我们仅在某些 (2/18) 无法恢复的容器上遇到以下异常。

堆栈跟踪:

org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:402)   ... 20 moreCaused by: 
java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30000ms.  at
com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:689)   at
com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:196)    at 
com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:161)    at
com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:128) at 
org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122)    at 
org.hibernate.internal.NonContextualJdbcConnectionAccess.obtainConnection(NonContextualJdbcConnectionAccess.java:38)    at
org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.acquireConnectionIfNeeded(LogicalConnectionManagedImpl.java:104)  
... 30 moreCaused by:org.postgresql.util.PSQLException: This connection has been closed.    at 
org.postgresql.jdbc.PgConnection.checkClosed(PgConnection.java:857) at 
org.postgresql.jdbc.PgConnection.setNetworkTimeout(PgConnection.java:1639)  at 
com.zaxxer.hikari.pool.PoolBase.setNetworkTimeout(PoolBase.java:556)    at 
com.zaxxer.hikari.pool.PoolBase.isConnectionAlive(PoolBase.java:169)    at 
com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:185)    ... 35 more

我们已经看到了类似(在同一系统上)的情况和测试,其中数据库故障转移和连接在 Hikari 上恢复而没有任何问题。但在这种情况下,其中一个容器在 1 小时后自行恢复,其他容器在重启后恢复。

据我们所知,Hikari 不会返回池中断开的连接,而是在标记为断开或关闭后将它们从池中逐出。任何想法可能发生在这些容器上而其他容器(完全相同的图像和配置)都很好。

PS:我们无法重现该问题。

Hikari 配置:

allowPoolSuspension.............假 connectionInitSql................无 connectionTestQuery.............无 连接超时......................30000 空闲超时.....................600000 初始化失败超时.......1 隔离内部查询........错误 泄漏检测阈值............0 最长寿命.....................1800000 最大池大小..................15 最小空闲.....................15 验证超时......................5000

【问题讨论】:

【参考方案1】:

您可以配置如下:

connectionTestQuery=select 1

这样 Hikari 会在将其处理给 Hibernate 之前测试连接是否仍然存在。

【讨论】:

嗨,从 Hikari 文档来看,它适用于旧版驱动程序,而我们并非如此。 ?connectionTestQuery 如果您的驱动程序支持 JDBC4,我们强烈建议不要设置此属性。这适用于不支持 JDBC4 Connection.isValid() API 的“旧版”驱动程序。这是将在池中为您提供连接之前执行的查询,以验证与数据库的连接是否仍然存在。同样,尝试在没有此属性的情况下运行池,如果您的驱动程序不符合 JDBC4,HikariCP 将记录错误以通知您。默认值:无 有趣,谢谢。我们在 mysql 上遇到了类似的问题,添加 connectionTestQuery 帮助很大,所以现在我不确定发生了什么

以上是关于数据库故障后的 Hikari CP (Spring Boot) 连接恢复问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring(4) 上下文中为 HSQL 配置 Hikari CP?

使用Hikari CP检测到明显的连接泄漏

2 具有不同数据源配置的 Hikari CP?

Hikari CP 检测到明显的连接泄漏

使用 Spring Boot 的 Mysql 的 Hikari 配置

mssql-jdbc MS SQL Server JDBC 驱动程序准备好的语句缓存性能问题与 Hikari CP