Druid连接池引发的线上服务卡慢宕机问题_druid连接池获取卡住_wf_feng的博客-程序员宅基地

技术标签: Druid  架构  java  性能、调优  

一、使用Druid背景

     公司微服务产品改造上线后,在开发环境的时候,使用的是springboot默认的连接池HikariCP,为什么springboot2.0后选择的是HikariCP,可以参考博客,Springboot 2.0选择HikariCP作为默认数据库连接池的五大理由https://blog.csdn.net/liuhuiteng/article/details/10762753。
     其实总结一句话就是HikariCP性能最高,可以pk掉其他所有的连接池;
     而我们在对产品进行压测后发现,程序经常卡在获取数据库连接上,经查公司产品底座对连接池的大小的都没有进行调整,默认是最大是8个连接,没有人员负责连接池,随即接手处理,之后就对连接增大,后面再进一步优化sql;
     做进一步的压测的时候,发现sql执行快慢情况,不能很好的监控出来,对性能调优有一定影响,当即决定切换阿里的Druid数据库连接池,并开启监控,发现真香啊;
     在性能对比上,Druid还是可以的。
在这里插入图片描述
     主要还是监控真的香,基于Druid强大的监控功能,有利于日常的开发工作、和线上的运维监控,同时可以基于接口自定义扩展监控;
在这里插入图片描述

二、问题出现及分析

1. 问题出现,快速确认问题类型

     云上某服务上线没几天反馈卡慢宕机,一上午陆续几个集群节点出现问题;

     随即和运维同事沟通确认应用的jvm内存正常,该服务对应的数据库实例负载正常,问题现象是某些节点正常,某些不节点不正常,当即确认为当时有问题节点应用这边阻塞导致;

     问题类型,卡慢宕机无非是应用的jvm内存溢出,数据库负载高,应用线程阻塞、各种资源泄漏(如redis连接泄漏,数据库连接池泄漏)等。

2. 取日志分析问题

     分析问题时间点日志,会发现很多的请求会卡在获取Druid连接池连接上,这种要反应过来,要么是池里面连接都拿去执行sql了,要么池里面的连接都泄漏了;
在这里插入图片描述
在这里插入图片描述

     如何判断连接都去执行sql了?
           在线程快照里面找mysql相关的,从连接池里面拿完连接,当然是执行sql了。
           如下图,正在执行的sql很少,那岂不是就是泄漏了?
在这里插入图片描述

     如何判断连接泄漏了呢?
           结合技术架构来看,除了Druid会去池里面的connection,业务地方取的可能性应该是极小的;
          反向之,如果是连接泄漏,那按照上图为什么还有8个连接没泄漏完(有一种情况,刚刚好泄漏仅剩8个连接,而刚刚好这8个连接执行的sql较慢,或者并发请求更高,可以进一步确认);
          当时直接认定没连接泄漏,然后做一步线程快照分析;

      进一步分析发现,还有请求在获取Druid连接池的connection的时候,会阻塞在以下的锁上waiting to lock <0x00000006c69c35f8> (a java.lang.Object)
在这里插入图片描述      进一步分析0x00000006c69c35f8锁占用问题发现,
在这里插入图片描述
这个当时我脑子是没有转过来的,什么卡在org.apache.catalina.loader.WebappClassLoaderBase.loadClass() 卡在类加载器加载class上了?为什么会卡? 没想通。。。愣是愣了几分钟;

然后又换了一个线程快照查看,如下图基本都是卡慢在同一个地方加载class
在这里插入图片描述
查看此处加载的class是com.mysql.jdbc.MysqlIO
在这里插入图片描述
然后去确认这个卡慢宕机服务里面搜索com.mysql.jdbc.MysqlIO,确实不存在这样的class,这种查找不存在的class,肯定是慢的,即classload会遍历所有的class目录,即涉及到磁盘IO,然后对于这种druid取连接和执行sql的情况是属于并发高的场景,很容易锁阻塞;

三、验证

     问题确认为druid加载不存在的class com.mysql.jdbc.MysqlIO 导致classload全盘扫描加载class目录导致的锁等待,线程阻塞问题;
在这里插入图片描述
     如何验证loadclass慢的问题?
           写一个demo,反射加载一个不存在的class,和反射加载一个存在的class即可;
     可以明显对比出加载不存在的class耗时可能在几十ms(和jar包数量有关);
     该服务里面为什么不存在com.mysql.jdbc.MysqlIO?
          这个看包名是属于mysql驱动包的,检查项目里面使用的是8.0高驱动版本,确实是不存在的;
在这里插入图片描述
然后到maven参考拉mysql的不同版本的驱动包,确认是mysql驱动包低版本6以后就不存在了;
在这里插入图片描述

四、解决

拉对应版本的Druid源码,简单的看下druid源码,按照以下处理注释掉loadclass,不加载不就没问题了吗;
在这里插入图片描述
然后专门打包了一个jar包,druid-weaver.jar ,修改架构框架druid依赖为druid-weaver.jar ,上传jar到私服解决;

根本解决方案

  上述直接 调整源码注释掉loadclass的逻辑,可以解决性能问题,但是某种情况下会导致获取链接不稳定。
  根本解决方案是 升级版本到 druid-1.1.23
  我们对比下源码:

1.1.22
在这里插入图片描述

1.1.23
在这里插入图片描述
在这里插入图片描述

五、后续

      该服务之后就没因为druid宕机,稳定运行,由于我们线上的服务节点多达200多个,部分并发高的业务服务之后也陆续出现问题,经确认也是同问题,影响较大;

六、Druid个别参数使用建议

test-on-borrow = true, 线上建议关闭,确实是很耗性能,在我们线上生产环境,我们有监控统计获取druid获取连接检测,基本每次检查要耗时几ms,一个请求执行上百sql,就是几百ms;建议关闭为false;
然后开启test-while-idle = true,防止连接失效有问题场景;

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/wf_feng/article/details/121665572

智能推荐

poi 3.1.1采坑记_weixin_39507514的博客-程序员宅基地

这里是pom.xml依赖 &lt;dependency&gt; &lt;groupId&gt;org.apache.poi&lt;/groupId&gt; &lt;artifactId&gt;poi-ooxml&lt;/artifactId&gt; &lt;exclusions&gt; &lt;exclusion&gt; &...

mongodb 用命令导入导出数据库,用命令在Robo3T 上查询。_robo3t导出数据_摸鱼的图图的博客-程序员宅基地

mongodb 用命令导入导出数据库,用命令在Robo3T 上查询。mongodb导入导出命令导入命令导出命令在Robo3T上查询mongodb导入导出命令快捷方式:如果没有配置mongodb的环境变量,可直接在mongodb的安装bin目录下,将相应的json文件复制到这里,去除json后缀名执行命令。需要配置环境变量的可自行百度。数据库名:test 密码:123456导入的数据表名:table1导进去的数据表名: table2当前ip地址和端口号:localhost:27017导入命令

自己封装的简单ThreadFactory_cyclethreadfactory_我是黄大仙的博客-程序员宅基地

简介自己封装的一个线程池工厂,能够比较方便的使用各种线程池,包括普通线程池、执行周期性任务线程池、单线程池,其中利用反射技术,可以直接传入函数名就可以执行,目前只支持无参函数的传入,也可以代码包装成Runnable传入。结构与功能整体结构如下图所示: ThreadFactory里面包含有四个线程池,分别是 单线程池:线程池只有一个线程,所有任务依次执行; 周期任务线程池:用于执行周期性的任

黑马程序员 JAVA学习笔记——java基础01_Dunamis的博客-程序员宅基地

------- android培训、java培训、期待与您交流! ----------

Matplotlib图例中文乱码_matplotlib 图例 中文_君只见独不见的博客-程序员宅基地

环境:win10 + Python3.6(anaconda) + IDE(Pycharm)问题:在使用matplotlib绘制图表时中文字符出现乱码(已作配置, 出错截图就不展示了)解决办法:一、在Python文件中使用matplotlib绘图时加入以下两行(import matplotlib.pyplot as plt)plt.rcParams['font.sans-serif'...

oracle常用hint_weixin_34417814的博客-程序员宅基地

2019独角兽企业重金招聘Python工程师标准&gt;&gt;&gt; ...

随便推点

boa下web页面动态刷新_boa 动态网页_q553716434的博客-程序员宅基地

ajaxtest.html文件Ajax + CGI Test获取服务器当前温度服务器当前温度 是:ajaxtest.js文件var xmlhttp;/**创建异步访问对象*/function createXHR(){ var xhr; try {

利用Pytorch的C++前端(libtorch)读取预训练权重并进行预测_老潘的博客的博客-程序员宅基地

关于本文章的最新更新请查看:oldpan博客看起来明天(2018-12-7)会发布Pytorch-1.0的稳定版。前言距离发布Pytorch-1.0-Preview版的发布已经有两个多月,Pytorch-1.0最瞩目的功能就是生产的大力支持,推出了C++版本的生态端(FB之前已经在Detectron进行了实验),包括C++前端和C++模型编译工具。对于我们来说,之后如果想要部署深度学习应用...

scaleType设置缩放类型_scaletype 按宽度缩放_爱桃酥的沐晨的博客-程序员宅基地

android:scaleType用于设置显示的图片如何缩放或者移动以适应ImageView的大小Java代码中可以通过imageView.setScaleType(ImageView.ScaleType.CENTER);来设置~可选值如下:fitXY:对图像的横向与纵向进行独立缩放,使得该图片完全适应ImageView,但是图片的横纵比可能会发生改变 fitStart:保持纵横比缩放图片...

谈谈php里的IOC控制反转,DI依赖注入_ccc82284的博客-程序员宅基地

理论发现问题在深入细节之前,需要确保我们理解"IOC控制反转"和"DI依赖注入"是什么,能够解决什么问题,这些在维基百科中有非常清晰的说明。控制反转(Inversion of Control,缩写为IoC):是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。依赖注入(Dependency Injection,简称DI):DI是IOC的一种实现,表现为:在类A的

Fragment详解_添码星空的博客-程序员宅基地

1、Fragment介绍 作为 Activity 界面的一部分,Fragment 的存在必须依附于 Activity,并且与 Activity 一样,拥有自己的生命周期,同时处理用户的交互动作。同一个 Activity 可以有一个或多个 Fragment 作为界面内容,并且可以动态添加、删除 Fragment,灵活控制 UI 内容,也可以用来解决部分屏幕适配问题。2、F

CentOS 6.5下JDK-1.8.111的安装配置_ning-wang的博客-程序员宅基地

0x01 环境说明 OS: CentOS-6.5-x86_64 JDK: jdk-8u111-linux-x640x02 安装部署2.1 下载到oracle官网下载jdk在这里你可以选择想要的jdk版本进行下载,不过一般太老的版本就很难下载到了,下载最新版jdk8。接受许可协议,然后选择相应的版本下载即可,这里选择[jdk-8u151-linux-x64.tar.gz](http://d

推荐文章

热门文章

相关标签