记一次druid连接池配置问题引发服务假死的定位、分析、解决过程

记录一次driud连接池的连接数用完问题 druid连接池的活跃连接达到最大连接数 阅读详情

一、前言

        记录一次服务假死的整个排查过程,服务基础为spring boot + druid + 多数据源切换,在请求过多(尤其是长事务请求)时,服务出现请求无响应的状况,之前未完结的查询也没有任何返回结果。

二、定位问题原因

        问题出现时,表现如下图,后台无任何报错,sql语句戛然而止,后续的查询被中断。这时如果再次发起某个请求,后台服务处于大部分时间不能收到新的请求的状态,或者偶尔可收到请求但不会执行crud。经过一段时间后,日志输出了session校验的内容,此时我推测服务并不是真的宕机,而是处于假死状态。

   

    druid配置如下

        

        看了下配置文件,最大连接池数量设置为100,但重现问题的过程不需要特别多的请求,稳妥起见,将最大数量改为200,问题没有解决,初步推测不是因为请求达到了连接池上限。

        CPU和内存均无异常。

         期间还优化过业务逻辑,甚至将同步请求改为异步请求,都无济于事。一筹莫展之际,想起了druid自带的监控功能。打开监控页面,找到了一处令我怀疑的地方。数据源中的逻辑打开和逻辑关闭次数起初是一致的,随着查询次数增多,逻辑关闭次数小于逻辑打开次数,于是我怀疑数据库连接池出现了泄露的情况,根据URI监控中显示的情况,jdbc出错数刚好等于逻辑打开与逻辑关闭次数的差,也就是说,很有可能由于jdbc出错导致数据库连接池未正确关闭。

(图片为部分截图,下面还有个1没有截到) 

        按着这个思路,对测试部分代码进行了排查,无果。后来根据druid官方的文档,找到了下面这段话。

         

        从这段话中可以看出,判断是否是泄露应该在URI监控中,点击URI进入详情页面,查看打开和关闭的数量是否相等。于是我在逻辑连接打开和逻辑连接关闭次数有巨大差异的情况下,对每一个URI都进行了核查,所有URI详情中,连接池获取连接次数都是等于连接池关闭连接次数的,理论上证明数据库连接池并无泄露。

        前面图中druid的文档中还提到了removeAbandoned等三个属性用以检测数据库连接池泄露,于是我将这三个属性写在了yml里。

        一通华丽丽的操作下来,服务依旧被玩坏,然后打开了druid的监控,找到了数据源页面中的ActiveConnectionStackTrace。点开,没数据???控制台也没输出日志??? 网上找了一些文章,然后大胆的怀疑是不是druid的配置没生效?再看一下druid运行时的数据源,果不其然。初始化连接大小、最小空闲连接数、最大连接数、超时时间等等等等,除了数据库指向是生效的,其他配置使用的都是缺省值。所以我即使把最大数量从100改成了200,依然是没几个请求就爆炸了。

 三、解决方案

        下面开始着手解决配置没生效的问题。由于项目是多数据源切换,于是找到了这个配置文件,尝试着改造了一下,将yml中的配置set到了DruidDataSource对象中。

      

(下图仅展示了与本文有关的内容) 

 
  1. @Configuration

  2. public class DruidConfig {

  3.  
  4. @Value("${spring.datasource.druid.initial-size}")

  5. private int initialSize;

  6.  
  7. @Value("${spring.datasource.druid.min-idle}")

  8. private int minIdle;

  9.  
  10. @Value("${spring.datasource.druid.max-active}")

  11. private int maxActive;

  12.  
  13. @Value("${spring.datasource.druid.max-wait}")

  14. private int maxWait;

  15.  
  16. @Value("${spring.datasource.druid.pool-prepared-statements}")

  17. private boolean poolPreparedStatements;

  18.  
  19. @Value("${spring.datasource.druid.max-pool-prepared-statement-per-connection-size}")

  20. private int maxPoolPreparedStatementPerConnectionSize;

  21.  
  22. @Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}")

  23. private int timeBetweenEvictionRunsMillis;

  24.  
  25. @Value("${spring.datasource.druid.min-evictable-idle-time-millis}")

  26. private int minEvictableIdleTimeMillis;

  27.  
  28. @Value("${spring.datasource.druid.test-while-idle}")

  29. private boolean testWhileIdle;

  30.  
  31. @Value("${spring.datasource.druid.test-on-borrow}")

  32. private boolean testOnBorrow;

  33.  
  34. @Value("${spring.datasource.druid.test-on-return}")

  35. private boolean testOnReturn;

  36.  
  37. @Value("${spring.datasource.druid.remove-abandoned}")

  38. private boolean removeAbandoned;

  39.  
  40. @Value("${spring.datasource.druid.remove-abandoned-timeout}")

  41. private int removeAbandonedTimeout;

  42.  
  43. @Value("${spring.datasource.druid.log-abandoned}")

  44. private boolean logAbandoned;

  45.  
  46. /**

  47. * 设置数据库连接池

  48. *

  49. * @author sunbin

  50. * @since 2020年4月21日

  51. * @version 2020年4月21日

  52. * @param dataSource

  53. */

  54. private void setDruidDataSource(DruidDataSource dataSource) {

  55. dataSource.setInitialSize(initialSize);

  56. dataSource.setMinIdle(minIdle);

  57. dataSource.setMaxActive(maxActive);

  58. dataSource.setMaxWait(maxWait);

  59. dataSource.setPoolPreparedStatements(poolPreparedStatements);

  60. dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);

  61. dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);

  62. dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);

  63. dataSource.setTestWhileIdle(testWhileIdle);

  64. dataSource.setTestOnBorrow(testOnBorrow);

  65. dataSource.setTestOnReturn(testOnReturn);

  66. dataSource.setRemoveAbandoned(removeAbandoned);

  67. dataSource.setRemoveAbandonedTimeout(removeAbandonedTimeout);

  68. dataSource.setLogAbandoned(logAbandoned);

  69. }

  70.  
  71. /**

  72. * 默认数据源

  73. *

  74. * @author 89390

  75. * @since 2019年4月15日

  76. * @version 2019年4月15日

  77. * @return

  78. */

  79. @Bean

  80. @ConfigurationProperties("spring.datasource.druid.master")

  81. public DataSource masterDataSource() {

  82. DruidDataSource dataSource = DruidDataSourceBuilder.create().build();

  83. setDruidDataSource(dataSource);

  84. return dataSource;

  85. }

  86. }

        重启服务,查看druid monitor,与yml中配置的一致了,即证明此时配置已经生效,再次测试,服务假死问题解决。

四、分析 

        项目中,spring boot版本为2.0.3.RELEASE

        druid版本为1.1.10

        

        考虑到版本等问题,虽然我们在yml中配置了druid连接池的其它属性,但是不会生效。因为默认是使用的java.sql.Datasource的类来获取属性的,有些属性datasource没有。如果我们想让配置生效,需要手动创建Druid的配置文件。由于项目中多数据源的功能,已经有了Druid的配置文件,所以无需新建,适当修改即可。

五、参考 

https://github.com/alibaba/druid/wiki/%E8%BF%9E%E6%8E%A5%E6%B3%84%E6%BC%8F%E7%9B%91%E6%B5%8B

https://www.cnblogs.com/SimpleWu/p/10049825.html

druid配置:回收线程remove-abandoned使用踩坑 本次踩坑springboot版本2.1.1 druid版本1.1.9 先讲下此次踩坑是怎么回事 项目本身为多数据源项目,第二数据源连接了一个只读db,因为该db从库需要进行迁移,所以让这边暂时先连接一下他们的主库,也就是读写库,本来就是改下配置文件重新发布的一件事,结果项目竟然上线后暴力测试几秒钟就挂了。赶紧看日志,发现是该数据源的连接池直接满了。。 报错如下: ### Error q... 阅读详情

相关推荐

Druid连接池与MySQL8.0的兼容性问题:从报错到解决的完整记录

本文深入剖析了Druid连接池与MySQL 8.0数据库交互时常见的`CommunicationsException`兼容性问题。文章从问题根源出发,详细解读了MySQL 8.0默认行为变化与Druid健康检查机制的冲突,并提供了从连接池配置调优、MySQL服务器参数调整到高级排查技巧的完整解决方案,帮助开发者彻底解决连接超时与假死难题。

q6r7s8t9的博客 1079

druid配置详解

无

m0_60731649的博客 806

【GaussDB】连接池探活失效引发Socket未关闭问题解析与优化实践

本文深入解析了GaussDB数据库因会话超时机制与应用连接池探活失效导致的Socket未关闭与I/O error问题。通过分析数据库的session_timeout机制与连接池工作原理,提供了从日志排查到实战配置的完整解决方案,并针对Druid、Tomcat JDBC Pool及HikariCP等主流连接池给出了具体的保活参数优化建议,确保连接池心跳快于数据库回收节奏,从而根治此类连接失效问题。

o9p0q1的博客 551

druid数据库连接池监控

设置了removeAbandoned="true"时,当连接池连接数到达(getNumIdle() < 2) and (getNumActive() > getMaxActive() - 3) [空闲的连接小于2并且活动的连接大于(最大连接-3)] 时便会启动连接回收,那种活动时间超过removeAbandonedTimeout="120"的连接将会被回收。logAbandoned=true,表示在回收连接的时候,在日志中输出回收的连接的信息,包括是在哪用的这个连接,可以用来追踪连接溢出。

weixin_42855525的博客 1292

Python-OpenCV及cv2,numpy库最新安装教程[最全步骤]

安装教程目录前言OpenCV-Python安装教程报错解决cv2安装numpy安装opencv安装(附加)总结 前言 首先,我知道一些看到我的Blog的人已经在网上找了很多歪路子,现在已经火冒三丈了(我也是这样过来的hhhh),那么现在,深呼吸,跟着我的教程,不要着急,每一步都要读一遍。完整安装过程需要1个小时左右(仅供参考,本人第一次安装python花了一天(确信)) OpenCV-Python...

qq_45425286的博客 7430

AWR1642+DCA1000EVM 不使用mmWave Studio软件采集原始ADC数据 Timeout问题汇总

DCA1000 EVM Timeout问题汇总

Jesy_Hsu的博客 1475

记阿里Druid数据连接池引发的线上血案

前言碎语 事件起因:项目使用了activiti工作流,系统是由老的spring mvc项目改造成的spring boot项目,数据库链接池从dbcp切换到druid,新系统上线后,同事多次系统隔一段时间后数据查询就很慢,基本出不来。由此开始了线上bug排查之路。这个问题从一开始就模糊定位到数据库层面的问题,因为只有和数据相关的操作会很慢,其他服务不受影响,并且在中午休息时没有问题,在下午刚上班后不就出现。 过程一:定位工作流 首先第一反应是看日志:日志一切正常,并没有任何异常信息抛出,然后将日志级别调

Aplumage的专栏 3120

TSMaster实战:手把手教你用C小程序发送自定义CAN报文(附完整代码)

本文详细解析了如何使用TSMaster的C小程序功能实现自定义CAN报文发送,涵盖环境配置、DBC集成、按键触发等实战技巧。通过完整代码示例和高级调试方法,帮助汽车电子工程师快速掌握TSMaster在CAN总线通信中的灵活应用,提升开发效率。

weixin_29184371的博客 574

【生产事故复盘】默认数据库连接池“假死”引发的血案,切换 Druid 后的重生之路

摘要:本文分析了分布式系统中数据库连接池的关键作用及默认配置的潜在风险。以HikariCP为例,指出其三大核心问题:未响应连接无法回收、缺乏主动故障干预和监控排查困难。针对连接阻塞问题,提出了四种常见场景及解决方案,并对比了HikariCP与Druid的特性,最终推荐使用具备主动连接管理能力和完善监控机制的Druid连接池。Druid通过连接泄漏自动回收、慢查询强制中断、全链路超时防护和可视化监控等机制,有效解决了连接耗尽问题。文章最后提供了连接队列阻塞的排查清单,包括事务范围检查、网络超时配置等关键步骤。

qq_39035267的博客 663

Python介绍与安装

Python介绍与安装

acegi13579的专栏 3219

避开这些坑!QMT多因子策略实盘中的5个常见错误及解决方案

本文深入剖析了在QMT平台上实施多因子策略时常见的5个错误,包括因子过拟合、数据延迟处理不当、因子失效、交易成本低估和风险控制缺失,并提供了实用的解决方案。通过优化因子筛选、数据对齐和动态管理,帮助量化交易者提升策略稳健性和实盘表现。

k5l6m的博客 238

Druid连接池超时问题排查:从服务不可用到长SQL锁定的深度解析

本文深度解析了Druid连接池超时导致服务不可用的排查与解决方案。通过从系统资源、JVM线程到内存快照的逐层分析,定位到连接池耗尽的核心问题,并解读了`max-wait`、`remove-abandoned`等关键配置的源码机制。文章进一步揭示了长SQL与数据库行级锁等待的根本原因,并提供了从监控、配置优化到代码规范的完整防护体系。

rgv23456789的博客 456

国科大学习资料--计算机视觉--期末考试解析

国科大学习资料–计算机视觉(胡占义)–期末考试解析 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

无名何许人的博客 2464

SpringBoot线上服务假死,CPU内存正常,什么情况?

背景开发小伙伴都知道线上服务挂掉,基本都是因为cpu或者内存不足,出现GC频繁OOM之类的情况。本篇文章区别以上的情况给小伙伴们带来不一样的服务挂掉。还记得哔哩哔哩713事故中那场诡计多端的0吗?对就是这个0,和本次事故没关系,但深受启发。问题排查老规矩在集群环境中同一个服务几个节点无响应。如不及时解决会可能形成雪崩效应。优先查看服务日志是否有报错,礼貌习惯性查看服务cpu及内存情况。先复习下,若...

Java知音 414

【KingSCADA】如何建立硬件系统及相关变量

本篇主要讲解如何定义设备,如何定义变量。KingSCADA3.8的采集系统是指负责和现场设备进行通讯,并采集现场数据和控制现场数据的模块,称之为采集器,也叫IOServer应用,它是一组独立的应用程序,可以脱离KingSCADA3.8软件,它依赖于KingSCADA3.8驱动产品,通过驱动与IO设备进行通讯。采集系统由通讯链路,设备,数据块组成。链路:链路是指计算机通过什么方式(接口)与设备进行连接,链路类别:串口,以太网,GPRS,Modem,通信卡,采集卡,无链路。

做有价值的事,积累有价值的笔记! 1万+

(四)美赛画图篇:画图模板+画图工具

美赛画图篇:画图模板+画图工具(一)画图模板(二)画图工具 因为散点图、折线图等多与数据有关,且需相关软件生成,故此处多是通用模板。直接替换文字内容即可。 (一)画图模板 1、Visio圆圈图 适合于:指标体系(E题常用) 点击下载:1 C币 如果不想花费且时间充足,悄咪咪地说,在visio-模板搜索可以找到很多。(稍微会耗一点时间) 2、简单指标体系图PPT 适合于指标体系 点击下载:0 C币...

weixin_43689393的博客 1万+

@Transactional连接池耗尽:Oracle+Druid下的事务资源陷阱

在Java企业级应用中,Spring的@Transactional注解常被误认为仅控制数据库原子性,实则直接绑定JDBC连接生命周期。其本质是事务开启时即向DataSource申请Connection,并全程独占直至方法结束——这导致事务执行时间≠SQL耗时,远程调用、IO或计算等非DB操作会无限延长连接占用。当与Oracle数据库(processes限制严格)及Druid连接池(testOnBorrow机制敏感)组合时,极易触发maxActive耗尽、Wait timeout、Communications

weixin_34184561的博客 425

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

SpringBoot 线上服务假死,CPU 内存正常,什么情况?

开发小伙伴都知道线上服务挂掉,基本都是因为cpu或者内存不足,出现GC频繁OOM之类的情况。:当前对象内存大小+当前对象直接或间接引用的对象大小,全部的总和,简单理解,就是当前对象被GC后,总共能释放的内存大小。经过上面一通手法操作,足以解决此类常规报错了,通常大多是原因各种循环递归、或数据库慢查询等。因服务健康监测无响应,cpu及内存情况正常,直接查看堆栈信息,看看线程都在干什么。报表很直观地展现了一个饼图,图中颜色深的部分表示可能存在内存泄漏的嫌疑。:表示对象自身占用的内存大小,不包括它引用的对象。

qq_52674658的博客 271

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Tongweb假死排查:JNDI锁阻塞与线程池队列引发的应用无响应

在Java应用服务器中,线程池的阻塞队列选择直接影响故障表现:无界队列会让请求无限排队,使应用陷入“有请求无响应”的假死状态。而JNDI作为统一资源注册中心,其lookup操作被设计为低频管理动作,一旦被置于高频业务路径且内部锁竞争加剧,就可能成为系统瓶颈。当网络线程池全部阻塞在JNDI锁上,后端连接池又被慢SQL占满时,应用就会呈现“转圈”现象。通过jstack抓取线程dump,可以精准定位锁持有链,从源头解决问题。以一次Tongweb环境下的生产事故为线索,完整展示了从现象、原理、排查到优化的过程,为中

weixin_29268637的博客 203

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

数据库连接池原理详解(连接复用、HikariCP优化、Druid监控、参数调优、连接泄漏排查)

数据库连接池是后端系统的基础组件。为什么需要连接池?连接池参数如何配置?HikariCP为什么比Druid快?连接泄漏如何排查?理解连接创建的开销、连接复用的性能提升、最大连接数的计算公式、连接泄漏的监控告警、HikariCP的无锁优化,才能掌握连接池的本质。从"数据库连接池耗尽导致服务假死"的故障出发,剖析连接池的核心原理。

比较是偷走幸福的小偷 1506

Datart连接数据库报错?手把手教你调优Druid连接池参数(附实战配置)

本文详细解析了Datart连接数据库报错的常见原因,并提供了Druid连接池参数的调优实战指南。通过诊断连接池状态、解剖核心参数、专项配置和五步调优法,帮助用户彻底解决连接池'假死'问题,提升BI系统的稳定性和性能。

weixin_28730353的博客 351

Tomcat假死问题深度排查:从线程死锁到内存泄漏的实战指南

在Java Web应用开发中,线程死锁和内存泄漏是导致服务不可用的两大核心问题。线程死锁通常源于不合理的同步机制或资源竞争,当多个线程相互等待对方持有的锁时,系统将陷入停滞。内存泄漏则由于对象无法被垃圾回收器释放,长期累积会引发频繁的Full GC甚至OutOfMemoryError,最终耗尽系统资源。这些问题在Tomcat这类Servlet容器中尤为突出,会直接导致应用进入“假死”状态——进程存活但服务无响应。通过系统性的排查方法,如分析线程转储(Thread Dump)定位阻塞线程,利用jstat监控G

weixin_30530939的博客 580

连接池失效——高并发下的隐形杀手

原因表现解决方案代码未归还连接活跃连接数持续上升事务过长连接占用时间长缩小事务范围慢SQL连接执行慢,排队优化SQL、加索引数据库重启连接全部失效并发突增连接不够用增大连接池、限流连接泄露活跃连接慢慢增加死锁连接互相等待优化锁顺序网络抖动连接假死连接超时检测连接池问题是"隐形杀手"——平时不出问题,一出就是大问题。日志里多次出现的"连接池泄露"、“连接占完”、“连接池故障分析”,每次都是系统快挂了才发现。事后分析原因都很简单:代码少了个close()

yuhou25的博客 639
上一篇: 手动创建DruidDataSource失败后死循环以及程序卡住的问题
下一篇: spring data jpa方法命名规则
qq_34412985
博客等级 码龄11年 143粉丝 983原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值