SpringBoot+Hikari+JPA环境下压测出现JDBC无可用连接问题求助
问题根因分析
从你提供的日志、配置和技术栈信息来看,你遇到的不是代码层面的主动连接硬泄漏,属于慢操作导致的连接软耗尽,核心逻辑如下:
- 日志中触发连接泄漏预警后,明确打印了连接最终被归还的记录,说明没有出现连接被永久占有的硬泄漏问题
- 压测失败前的连接池指标显示:总连接数15全部处于活跃状态,无空闲连接,同时有75个请求在排队等待连接,当等待时长超过你配置的
connectionTimeout(30秒)后,就会抛出无可用连接异常,业务线程进入pending状态 - 你调整
connectionLeakThreshold到30秒仍然复现问题,是因为该参数只是连接泄漏预警的触发阈值,拉长阈值不会解决连接被长时间占有的根本问题
排查与解决方案
1. 优先排查JPA/DB层面的慢操作
- 排查慢SQL:检查是否存在未加索引的大表查询、批量查询未分页、关联查询逻辑不合理的情况,这类慢SQL会长时间持有连接不释放
- 排查大事务:检查
@Transactional注解的使用范围,是否存在把RPC调用、本地IO处理、缓存操作等非DB逻辑包在事务内的情况,事务未提交前连接不会归还到连接池,会大幅拉长连接持有时间 - 排查懒加载使用问题:如果开启了Hibernate懒加载,避免在事务外调用懒加载属性,这类操作会每次都重新申请连接,额外消耗连接池资源
2. 优化Hikari连接池配置
- 调整
maximumPoolSize:你当前的总连接数只有15,对于压测场景明显偏小,可根据数据库侧的最大连接数限制,调整到20~50区间(MySQL单实例最优活跃连接数通常不超过50) - 校验
maxLifetime参数:确保该参数值比数据库侧的wait_timeout配置小至少30秒,避免拿到数据库已经主动关闭的无效连接,浪费连接池资源 - 开启连接池指标采集:持续监控连接等待时长、连接持有时长、活跃连接数等指标,快速定位持有连接时间过长的具体业务接口
3. 临时验证方案
可先将maximumPoolSize临时调整为30,重新发起压测:如果问题缓解,说明是原连接数配置过小叠加业务慢操作共同导致;如果问题仍然复现,可针对性排查耗时Top10的业务接口的DB操作逻辑。
内容的提问来源于stack exchange,提问作者Chandan Gupta
相关产品推荐
相关产品推荐

