记一次生产数据库连接池大量连接超时问题排查
最近一段时间公司业务量上来了,与此同时伴随着程序猿终生的问题出现了。服务异常总体的表现就是每天不定时间出现访问超时并持续一段时间,偶尔又好了。刚开始出现次数很少,服务中断一小段时间后就自己恢复了。但随着时间推移,这种情况出现频率变高了,而且持续时间也变久了。老板此时的状态中断服务怎能忍,我打起了12分精神,开始排查问题,既然是数据库连接池抛出的问题,首先检查是不是数据库连接池参数出问题了,有长事务
最近一段时间公司业务量上来了,与此同时伴随着程序猿终生的问题出现了。
服务异常总体的表现就是每天不定时间出现访问超时并持续一段时间,偶尔又好了。刚开始出现次数很少,服务中断一小段时间后就自己恢复了。但随着时间推移,这种情况出现频率变高了,而且持续时间也变久了。
中断服务怎能忍,我打了个哈欠起了12分精神,开始排查问题,既然是数据库连接池抛出的问题,首先检查是不是数据库连接池参数出问题了,如有长事务占用或并发数过多导致连接池连接耗尽,然后一顿参数调整(如适当增加数据库连接池连接数量),发现效果不大。与此同时,我注意到另一个相关的服务使用了和此服务相同的数据库连接池配置,未发生过超时问题。斗胆猜测,问题不在数据库连接池配置。同时,也咨询了相关业务人员,发现是在操作部分节点(主要是网络传输附件,资料比较大)时容易出现超时现象,意识到可能是JVM内存不足。那就来个简单暴力点的,增加服务器配置,给服务分配更大的内存,同时采用多机部署,然后信誓旦旦的给老板说服务器配置过低,需要升级。下班后,一顿操作,完成了升级。
第二天,一早老板反馈还是会有超时现象,此时感觉老板每分每秒都在盯着,我压力好大呀!果不其然,当天还是多次出现了问题,继续摸索着,当然,方向已经从连接池转向虚拟机。通过JVM相关指令查看内存状态信息,发现了频繁FULL GC现象。脑袋瓜子疯狂运转,估摸着应该是内存耗尽,导致在执行对应的数据库查询时,无法创建相关资源导致的。思绪如狂风乱舞,心想,dump一份JVM文件分析下就好了,说时迟那时快,生产问题不容耽搁,立马修改了一下配置,内存溢出时,保留现场数据。当超时再次来临时,我准备下载相关文件并解析,发现文件过大,一般工具无法下载(下载一次,发现文件不完整,原因竟是因为磁盘空间不足),不论生产还是本地机器都无法分析如此大的文件,我内心已经崩溃毫无波澜,文件怎么会有这么大呢,我把部署配置拿过来一看,发现了不一样的地方,JVM参数均是手动配置,如-Xms、-Xmx、-XX:CompressedClassSpaceSize等,开始无限回想,项目启动后就占用了大量内存,这块肯定出问题了。随后将此配置恢复默认,问题短期内基本没有复现。
从问题解决过程来看,是JVM参数设置不当,导致项目经常OOM,究其原因,主要是如下几种情况造成:
- JVM堆内存溢出(如java.lang.OutOfMemoryError:Java heap space)
- JVM元空间内存溢出(如java.lang.OutOfMemoryError: Compressed class space)
- JVM GC开销时间过大(如java.lang.OutOfMemoryError: GC overhead limit exceeded)
- JVM直接内存溢出(如java.lang.OutOfMemoryError: Direct buffer memory)
- JVM并发过高(如java.lang.OutOfMemoryError: unable to create new native thread)
针对如上情况,本文不做详细阐述,后续会将这部分单独做细致的讲解。
上文说到,短期内是没有问题,但随着项目运行时间推移,OOM问题复现,此时再通过相关指令查询JVM信息,发现其占用内存越来越大。第一感觉就是发生内存泄漏了,可以通过参数配置FULL GC时导出dump文件,也可以通过jmap手动将其导出(生产环境谨慎操作,会导致Java进程挂起,造成服务中断),然后通过Jprofiler对此文件进行分析,大家可以查阅相关资料进行内存泄漏代码定位。
更多推荐
所有评论(0)