• 背景
    最近和其他组的小伙伴在联调施工代码时,发现工单下发后一直阻塞在组件控制台几个小时都没有返回,查看日志后发现是后端数据库挂掉的原因,但是按照之前使用的情况,spring boot 默认情况下数据库连不上是会直接返回。针对该情况本地启动原项目代码进行模拟
  • 问题排查
  1. 先关闭后端测试库,调用下单接口,这里使用的是idea自带的http client来发送请求,然后进入阻塞
  1. 使用jps查找对应的java进程,获取pid
  2. 通过jstack保存线程快照
  3. 在堆栈信息中,根据内部方法名找到阻塞的线程,然后查找到阻塞的位置,一般是等待锁或者根据某些条件进入等待。最终确定问题为调用了druid连接池的takeLast()方法,后续触发了某个条件变量(结合环境来看,现在连接池没有连接,应该是notEmpty条件)的await方法,从而进入条件队列阻塞

druid数据库连接池testOnBorrow是否要开启 druid数据库连接池阻塞_条件变量

  1. 查看对应的源码来查找具体原因,最终发现,当maxWait这个变量<0时,就会进入无超时设置的获取,连接池为空时一直阻塞。

druid数据库连接池testOnBorrow是否要开启 druid数据库连接池阻塞_java_02

  1. 翻阅其他同事设置druid数据源的代码,发现确实没有设置maxWait这个变量,好吧找到问题了,可以进行批斗了。。
  2. 因为记得之前使用spring默认配置时获取连接失败是不会阻塞的,故去掉druid使用默认的hikari连接池继续测试,实验结果与预期一致,翻看相关代码确实也没有相关的条件变量属性。
  • 总结
    使用druid作为数据库连接池时一定要对必要的属性根据环境进行合适的设置,防止出现一些隐藏bug,而经过对比验证,大胆猜测druid的开发者是认为后端数据库一般是在用户自定义的maxWait时间内可以恢复所以设置对应的阻塞操作,使得相关调用尽可能的返回结果,对调用方比较友好