数据库很多异常的会话
系统的用户操作响应缓慢,数据库很多异常的会话,maxWait这个属性值Druid默认值是-1,导致连接池被占满,数据库连不上一直占用
故障现象
问题影响时间:7月12号 08:21点-09:30点
现象:无法进入系统,已进入系统的用户操作响应缓慢
故障处理过程
08:52 A开始反馈 xx-prod 进不去,数据库很多异常的会话
08:57-09:15 B进通过grafna和数据库库行了问题的定位,重启应用
09:18 实例重启成功后,问题依然无法正常服务
09:20-09:25 C通过慢请求定位到申请单查询接口特别慢,定位到是阿里商旅服务的异常
09:30 D 重启阿里商旅服务,重启后,实例开始正常工作。
故障原因
- 阿里商旅服务异常。通过分析stack,主要是拿不到数据库的链接,导致ice 线程池被占满,导致其他的请求无法请求。导致代码拿不到连接的原因如下:
- 分析堆栈信息发现大部分的线程都是阻塞的状态
b. 分析具体的某个阻塞的线程,发现是因为事务导致的拿不到链接导致的
c. 通过堆栈信息,可以发现是事务的注解不规范导致的。不应该在类上添加事务的注解,应该加在具体的方法上。
- ice 框架的超时时间设置没有生效。阿里商旅这个服务比较特殊,依赖了钉钉的sdk,只用的jdk1.8,所有的jar包有没有升级到最新的,目前service-common 已经更新到3.2.23,而阿里商旅用的还是1.5.6 。
- 代码中的逻辑不是最优的,报销单关联申请单明细的时候,遍历申请单的明细接口,返回了申请单的所有信息,可以修改为只返回前端需要的信息。
首先从stack中可以看出来:
这里大量的ICE线程在进入了DruidDataSource#takeLast方法后就进入了WAITING的状态;
因此查看了下这个服务用到的Druid版本(1.1.21)对应的代码:
可以看到notEmpty#await方法让当前线程一直进入WAITING状态等待唤醒。
进入这个分支,说明DruidConnectionHolder连接池容器中没有连接了,因此一直等待有空闲线程去唤醒,同时,这里没有设置超时时间,理论上会一直占用着当前线程,因此线上会出现ICE线程池满的情况(其实是大量线程都在waiting)。
回到最开始的入口方法DruidDataSource#takeLast,进入这个方法的前提是maxWait小于0(默认是-1),如果我们设置maxWait > 0,就会进入有超时时间的分支,线程会尝试获得锁,超过超时时间直接返回null,可以避免线程一直WAITING
maxWait这个属性值Druid默认值是-1,可以显式通过设置maxWait的方式来优化,设置一个合理的预期时间值,释放ICE线程去做其他事不要因为数据库连不上一直占用
反思与改进方案
系统的用户操作响应缓慢,数据库很多异常的会话,maxWait这个属性值Druid默认值是-1,导致连接池被占满,数据库连不上一直占用
相关文章
- Ness SES首席技术官:最终,Hadoop老了!
- 两会大数据:90后更关注收入,70后更关注教育
- 用于大数据处理高性能计算的4个实现步骤
- 一行代码,Pandas秒变分布式,快速处理TB级数据
- 数据分布式了,计算也得跟上!
- 数据科学研究的现状与趋势全解
- 这5种数据可视化方式是数据科学家标配!
- 数据中心能耗问题待解 边缘计算或开启新蓝海
- 两会大数据,00后成新关注者
- Apache Spark 2.3重要特性介绍
- 让大数据可视化,艺术家想用它帮我们选择更好的朋友
- PHP实现最简单的聊天室应用
- 人工智能将加快银行业转型!大数据会对每个用户进行信用评级!
- Hadoop进入寒冬期,崛起的会是Spark吗?
- 每个数据科学家都应该知道的六个概率分布
- 看了数据你就知道中国人有多能花
- 如何成为数据科学家? 数据科学家的职责技能要求和薪水构成
- 公厕大数据:东莞覆盖率最高北京数量最多
- 批处理ETL已死,Kafka才是数据处理的未来?
- 管理者在数据分析上常犯的9个错误