一次线上数据库连接池故障复盘

Posted 码农走向艺术

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一次线上数据库连接池故障复盘相关的知识,希望对你有一定的参考价值。

       用户反馈系统不可用,立即检查监控大盘和系统日志,发现系统有毛刺,因为在服务不可用的情况下,用户多次请求,导致请求量剧增

同时系统向下游系统的请求报文量骤降

一次线上数据库连接池故障复盘

查看日志文件,发现dbcp连接池异常关闭:

于是立即重启了进程,服务恢复正常。但过了20分钟左右,相同的问题再次发生,如下图所示,每隔一段时间,对外请求量消失:

 

一次线上数据库连接池故障复盘

此时,通过jstack –F 进程号>>stack.log生成stack快照,发现有很多WAITING的线程。

 这个异常事实上跟日志文件中dbcp连接关闭是一个意思,但还未定位dbcp异常关闭的原因。通过IBMjca工具打开stackdump文件。检查线程状态,发现runnable的几个线程都是同一个类的线程,都在调用一个外部依赖接口:

检查了一下该接口,发现该接口处于不可用状态,而calling该接口的方法启用了事务控制,使用springtransactional注解中未添加超时时间,默认超时时间是-1,也就是最长时间;同时方法块中的resttemplate也未配置超时时间,所以当该接口超时异常时,事务一直处于挂起状态,导致事务超时,连接被关闭,运行一段时间dbcp连接全部被数据库端关闭,从而导致数据源关闭,整个进程被挂起。


 

经验总结:

1.    事故原因是启用数据库事务时,由于超时导致数据库连接被动关闭,触发dbcp关闭连接池,进程处于hang状态,所有请求不再处理。

2.    线上故障时,先记录现场log,例如jstackheapmemory

3.    然后再重启机器。

4.    重启后要持续观察一段时间,确保故障消失。

5.    stack日志中有很多waiting线程,这些状态常常是表象,要重点检查runnable的线程。

6.    代码中,事务控制部分必须设置超时时间,要么及时提交,要么超时或异常回滚;事务控制的代码尽可能精简,只控制数据库访问部分。Springresttemplate用之前配置超时时间,连接数等关键参数。


    推荐!推荐!推荐! 获取每天更新的码农场原创内容       

 

   码农走向艺术

以上是关于一次线上数据库连接池故障复盘的主要内容,如果未能解决你的问题,请参考以下文章

故障复盘:数据库连接池

记一次线上环境 ES 主分片为分配故障

记录一次线上 Oracle 数据库 ORA-00060: deadlock detected 故障案例

记一次线上故障--HashMap在多线程条件下运行造成CPU 100%

记一次线上故障--HashMap在多线程条件下运行造成CPU 100%

记一次线上故障--HashMap在多线程条件下运行造成CPU 100%