一次线上数据库连接池故障复盘
Posted 码农走向艺术
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一次线上数据库连接池故障复盘相关的知识,希望对你有一定的参考价值。
用户反馈系统不可用,立即检查监控大盘和系统日志,发现系统有毛刺,因为在服务不可用的情况下,用户多次请求,导致请求量剧增:
同时系统向下游系统的请求报文量骤降:
查看日志文件,发现dbcp连接池异常关闭:
于是立即重启了进程,服务恢复正常。但过了20分钟左右,相同的问题再次发生,如下图所示,每隔一段时间,对外请求量消失:
此时,通过jstack –F 进程号>>stack.log生成stack快照,发现有很多WAITING的线程。
这个异常事实上跟日志文件中dbcp连接关闭是一个意思,但还未定位dbcp异常关闭的原因。通过IBM的jca工具打开stackdump文件。检查线程状态,发现runnable的几个线程都是同一个类的线程,都在调用一个外部依赖接口:
检查了一下该接口,发现该接口处于不可用状态,而calling该接口的方法启用了事务控制,使用spring的transactional注解中未添加超时时间,默认超时时间是-1,也就是最长时间;同时方法块中的resttemplate也未配置超时时间,所以当该接口超时异常时,事务一直处于挂起状态,导致事务超时,连接被关闭,运行一段时间dbcp连接全部被数据库端关闭,从而导致数据源关闭,整个进程被挂起。
经验总结:
1. 事故原因是启用数据库事务时,由于超时导致数据库连接被动关闭,触发dbcp关闭连接池,进程处于hang状态,所有请求不再处理。
2. 线上故障时,先记录现场log,例如jstack,heap,memory。
3. 然后再重启机器。
4. 重启后要持续观察一段时间,确保故障消失。
5. stack日志中有很多waiting线程,这些状态常常是表象,要重点检查runnable的线程。
6. 代码中,事务控制部分必须设置超时时间,要么及时提交,要么超时或异常回滚;事务控制的代码尽可能精简,只控制数据库访问部分。Spring的resttemplate用之前配置超时时间,连接数等关键参数。
推荐!推荐!推荐! 获取每天更新的码农场原创内容
码农走向艺术
以上是关于一次线上数据库连接池故障复盘的主要内容,如果未能解决你的问题,请参考以下文章
记录一次线上 Oracle 数据库 ORA-00060: deadlock detected 故障案例
记一次线上故障--HashMap在多线程条件下运行造成CPU 100%