一次 Druid 连接池泄露引发的血案!

请问下,一次 Druid 连接池泄露引发的血案!
最新回答
愛你不愛你

2026-05-24 10:04:01

答案:通过启用Druid连接池的强制回收功能(removeAbandoned)并配置超时时间(removeAbandonedTimeoutMillis)及日志记录(logAbandoned),成功定位并解决了连接泄露问题。但需注意生产环境谨慎使用,避免误回收长时间运行的事务。

问题分析
  1. 现象:应用程序频繁卡顿,需重启恢复,日志显示Druid连接池达到最大值(maxActive=50),获取连接超时(wait millis 60000)。
  2. 根本原因:代码中存在未正确释放数据库连接的情况,导致连接池耗尽。
解决步骤
  1. 启用连接泄露检测配置:

    removeAbandoned=true:开启强制回收未释放的连接。

    removeAbandonedTimeoutMillis=600000:设置超时时间为600秒(10分钟),超时后强制回收。

    logAbandoned=true:记录泄露连接的堆栈信息,辅助定位问题代码。

  2. 配置效果:

    Druid在连接池初始化时启动后台线程(createAndStartDestroyThread),定期检查超时未归还的连接。

    超时连接被强制回收,同时打印堆栈日志(如示例中的owner thread: https-jsse-nio-4443-exec-9),直接指向未关闭连接的代码位置。

  3. 定位问题代码:

    根据日志中的堆栈信息(如DruidDataSource.getConnectionDirect和AbstractRoutingDataSource.getConnection),可追溯到Spring事务管理或手动获取连接后未关闭的代码段。

注意事项
  1. 生产环境风险:

    若业务事务执行时间较长(超过removeAbandonedTimeoutMillis),可能被误回收,导致数据不一致。

    建议:生产环境谨慎启用,或根据业务调整超时时间(如延长至30分钟)。

  2. 替代方案:

    代码审查:全局检查Connection、Statement、ResultSet是否在finally块中关闭。

    工具辅助:使用Arthas等工具动态追踪连接获取/释放流程。

关键配置代码<property name="removeAbandoned" value="true" /><property name="removeAbandonedTimeoutMillis" value="600000" /><property name="logAbandoned" value="true" />总结

通过Druid的泄露检测配置,快速定位了连接未释放的代码位置,解决了连接池耗尽问题。但需权衡功能与风险,避免在生产环境中误伤正常长事务。建议结合代码规范和监控工具,从根本上杜绝连接泄露。