背景

生产环境有个关键应用所有节点,每隔几个月就会发生一次Druid连接池耗尽问题,重启后恢复正常。

目前我们还没有定位到问题原因,这边文章主要记录定位过程的一些思路和方法,后续如果找到根本原因,再做更新。

思路

数据库方向

应用连接池耗尽

1、会不会是应用与数据库的连接没有正常断开?

查看故障时数据库socket连接情况,没有发现。

2、会不会是应用执行了很多慢sql?

查看故障时数据库慢sql日志,没有发现。

3、会不会是应用执行了长事务?

查看故障时数据库事务情况,没有发现。

应用方向

应用连接池耗尽

1、会不会是应用受到攻击,突然收到大量请求?

通过对比故障时段和正常时段应用日志量级,没有发现。

2、应用的线程堆栈信息能不能看到什么操作占用大量数据库连接?

应用故障时通过jstack输出堆栈信息,所有线程阻塞在com.alibaba.druid.pool.DruidDataSource.pollLast(DruidDataSource.java:1944),也只有现象没有原因。

Druid方向

思考:能不能在应用故障时,输出Druid连接池活跃连接线程堆栈信息,辅助排查问题?

Druid有提供Web站点查看内部运行信息,地址:应用ip:port/druid/login.html

它有activeConnectionStackTrace-{datasourceId}.json端点可以获取活跃连接线程堆栈信息,datasourceId需要通过datasource.json端点获取输出中Identity的值。让人困惑的是,activeConnectionStackTrace-{datasourceId}.json端点要有输出,需要设置Druid的参数removeAbandoned=true

通过查看源码,我们发现DruidDataSource有getActiveConnectionStackTrace方法,可以获取活跃连接线程堆栈信息。这样我们可以自己在应用中定时检测DruidDataSource活跃连接数量,一旦超过某个阈值,就输出活跃连接线程堆栈信息到日志,辅助排查问题。

总结

这个关键应用连接池耗尽问题存在已有半年之有,一直没能找到根本原因,希望这次借助DruidDataSource输出连接线程堆栈信息能找到问题原因。

如果大家知道原因或有更好的定位方法,请不吝赐教。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐