SpringBoot+HikariCP数据库连接池耗尽问题求助
问题
在Kubernetes集群上部署的SpringBoot开发的Restful微服务进行负载测试时,遇到数据库连接池容量问题。添加Hikari配置后测试结果有所改善,但仍偶尔出现“连接不可用、连接超时”的数据库连接错误。停止负载测试后单独调用服务,依然会出现该错误,最终只能通过重置Pod解决。想请教:Pod是否会自行恢复正常,还是必须重启Pod(即重启JVM)?请给出建议。
配置文件(application.properties)
spring.datasource.url=jdbc:oracle:thin:.... spring.datasource.username=test spring.datasource.password=test spring.datasource.driver-class-name=oracle.jdbc.OracleDriver spring.main.allow-bean-definition-overriding=true #connection pool configuration spring.datasource.hikari.pool-name=SVConnectionPool spring.datasource.hikari.maximum-pool-size=60
错误日志
2023-07-19T05:59:46.455208060Z at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.base/java.lang.Thread.run(Thread.java:834) 2023-07-19T05:59:46.455436540Z Caused by: java.sql.SQLTransientConnectionException: SVConnectionPool - Connection is not available, request timed out after 76386ms. 2023-07-19T05:59:46.455448334Z at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:696) 2023-07-19T05:59:46.455481188Z at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:197) 2023-07-19T05:59:46.456083667Z at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:162) 2023-07-19T05:59:46.456094566Z at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:128) at org.springframework.jdbc.datasource.DataSourceUtils.fetchConnection(DataSourceUtils.java:159) at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:117) 2023-07-19T05:59:46.456286268Z at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80) ... 88 more 2023-07-19T05:59:46.456769448Z org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLTransientConnectionException: SVConnectionPool - Connection is not available, request timed out after 76386ms.
回答
Pod不会自行恢复
当前连接池耗尽且停止负载后仍报错,说明连接池已处于“死锁”状态:要么所有连接被占用未释放,要么连接已失效但未被清理。Hikari默认没有自动彻底重置连接池的机制,JVM也不会主动修复这种状态,因此Pod无法自行恢复,必须重启Pod才能重置连接池。临时应急方案:自动重启Pod
在Kubernetes中配置存活探针(Liveness Probe),当检测到数据库连接超时错误达到阈值时自动重启Pod。比如实现一个健康检查接口,尝试获取数据库连接,失败则返回非200状态码,触发Kubernetes重启Pod。根本修复方案
- 补充Hikari关键配置:仅配置最大连接数不足以避免连接失效和泄漏,需添加以下配置:
# 连接超时时间(默认30秒,可按需调整) spring.datasource.hikari.connection-timeout=30000 # 连接最大存活时间,避免Oracle断开闲置连接 spring.datasource.hikari.max-lifetime=1800000 # 闲置连接回收超时时间 spring.datasource.hikari.idle-timeout=600000 # 连接有效性检测SQL spring.datasource.hikari.connection-test-query=SELECT 1 FROM DUAL - 排查连接泄漏:开启Hikari泄漏检测,添加
spring.datasource.hikari.leak-detection-threshold=2000(单位毫秒),日志会输出连接泄漏的堆栈信息,定位未正确关闭连接的代码(比如未使用try-with-resources语法)。 - 匹配数据库连接上限:确保Hikari的
maximum-pool-size不超过Oracle实例允许的最大连接数(可通过SELECT value FROM v$parameter WHERE name='processes'查询),避免数据库拒绝新连接请求。
- 补充Hikari关键配置:仅配置最大连接数不足以避免连接失效和泄漏,需添加以下配置:
Kubernetes层面优化
- 配置Pod水平扩缩容策略,负载升高时自动增加Pod数量,分散单Pod的连接池压力。
- 添加就绪探针(Readiness Probe),确保Pod连接池初始化完成后才接收流量,避免无效请求。
内容的提问来源于stack exchange,提问作者KVNS_JavaLearner
相关产品推荐
相关产品推荐

