某个系统上线后出现连接池耗尽,如何一步步排查。可能还需要引用知识库中的具体配置示例,比如HikariCP的配置参数,或者Druid的监控方法。
遇到了线上连接池耗尽的问题,想要了解如何快速定位和解决。
某核心业务系统上线后,用户反馈访问缓慢,部分接口出现超时甚至报错。通过监控平台查看,发现服务端异常日志中频繁出现如下错误:
textCaused by: java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30000ms.
这表明 数据库连接池资源已经耗尽,请求无法获取数据库连接,导致服务不可用。
接口响应超时、数据库连接超时异常(如 SQLTransientConnectionException)。
监控指标:
HikariCP 配置示例:
yamlspring:
datasource:
hikari:
#最小空闲连接,默认值10
minimum-idle: 5
# 连接池大小及超时等配置
maximum-pool-size: 20
# 空闲连接超时时间,
idle-timeout: 30000
# 连接超时时间
connection-timeout: 30000
pool-name: pool-1
监控工具:
关键指标:
代码审查重点:
问题代码:
java@Resource
private PlatformTransactionManager transactionManager;
public void queryData() {
TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionDefinition());
// 代码异常,导致没有提交与回滚
....
try {
} catch (Exception e) {
transactionManager.rollback(transaction);
} finally {
if (Objects.nonNull(transaction) && transaction.isNewTransaction() && !transaction.isCompleted()) {
transactionManager.commit(transaction);
}
}
}
MySQL 慢查询日志:
sqlSHOW VARIABLES LIKE 'slow_query_log';
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1; -- 执行时间超过 1 秒的查询记录日志
工具辅助:
示例命令:
shjstack <pid> | grep "HikariPool" -A 20 # 查找连接池相关线程
现象: 请求卡死无响应,线程数居高不下,CPU 可能不高但吞吐为零或极低。
jstack 分析线程状态:
BLOCKED (on object monitor): 明显锁竞争。查找持有锁的线程和等待锁的线程堆栈,定位竞争资源。
WAITING (parking, on condition, on monitor) / TIMED_WAITING: 等待条件满足(如 Object.wait(), Condition.await())或 I/O 操作。检查是否条件未唤醒或 I/O 超时。
死锁检测: jstack 输出末尾通常会报告 Found one Java-level deadlock,列出死锁线程和锁信息。分析相关代码的同步逻辑。
检查锁使用: 是否过度使用 synchronized 或粗粒度锁?是否该用并发集合 (ConcurrentHashMap) 或更高级的锁 (StampedLock, ReadWriteLock)?
资源等待: 数据库连接池耗尽、HTTP 连接池耗尽、文件句柄耗尽等也会导致线程阻塞。检查相关资源池状态。
注意
数据库连接池耗尽、HTTP 连接池耗尽、文件句柄耗尽等也会导致线程阻塞,需要检查相关资源池状态。
DB 连接池耗尽问题的核心在于 连接资源管理不当,需从配置、代码、数据库优化和监控四个方面综合解决。
本文作者:柳始恭
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!