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

技术标签: 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

智能推荐

Java线程(七):锁对象Lock-同步问题更完美的处理方式-程序员宅基地

文章浏览阅读151次。上一篇:Java线程(六) Lock是java.util.concurrent.locks包下的接口,Lock 实现提供了比使用synchronized 方法和语句可获得的更广泛的锁定操作,它能以更优雅的方式处理线程同步问题,我们拿Java线程(二)中的一个例子简单的实现一下和sychronized一样的效果,代码如下:public class LockTest { p..._线程同步 lock对象

Java动态编译JavaCompiler_java 动态编译导入包-程序员宅基地

文章浏览阅读3.9k次。一、tools.jar问题:Java在进行动态编译的时候需要用到tools.jar资源包,此包在jdk\lib目录中。若tools.jar不存在则会出现进行编译时提示空指针异常:对于缺少jar包,首先想到的解决办法是找到需要的jar包并且将其加入到buildpath,但是我们发现只是将tools.jar加入到java buildpath中仍然会出现空指针异常。后来经过查询相关资料,java..._java 动态编译导入包

openwrt安装aliddns使用阿里云ddns_aliddns ipk-程序员宅基地

文章浏览阅读2.9w次,点赞2次,收藏11次。openwrt安装aliddns使用阿里云ddns一些小伙伴安装了openwrt之后发现没法使用阿里云的ddns解析这里告诉你怎么添加aliddns插件需要会一些linux基础命令和ssh分四步安装依赖下载插件上传插件安装插件安装ddns-scripts、luci-app-ddns、openssl-util、wget 依赖包使用luci web界面里面的软件包管理,或者ssh使用opkg安装都一样有的openwrt自带的源地址可能下载很慢或根本无法下载,得换源下载alid_aliddns ipk

【最全笔记】基础Python爬虫入门,看完包你会写爬虫_python爬虫知识笔记集合-程序员宅基地

文章浏览阅读856次,点赞3次,收藏24次。第一章 网络爬虫之规则一、Requests库入门request库:http://www.python-requests.org安装方法:pip install requests抓取百度import requestsr=requests.get("http://www.baidu.com")r.status_coder.encoding='utf-8'r.textre..._python爬虫知识笔记集合

[cdq分治] bzoj3262: 陌上花开_cdq分治bzoj-程序员宅基地

文章浏览阅读179次。bzoj 3262: 陌上花开:http://www.lydsy.com/JudgeOnline/problem.php?id=3262三维偏序(向我一样不懂啥偏序的先戳这里:http://www.cnblogs.com/AKCqhzdy/p/8017372.html) 第一个维度直接排序解决 第二个维度的话cdq搞一搞 符合条件就直接丢到树状数组里去 sum=树状数组的getsum..._cdq分治bzoj

[OpenBMC] 简单解析 smbios-mdr_bmc entity manager configuration-程序员宅基地

文章浏览阅读2.2k次。(*如果之后架构有变,这边不会更新)smbios-mdrGitHub - openbmc/smbios-mdrhttps://github.com/openbmc/smbios-mdrMDR(Managed Data Region) 是 OpenBMC中取得SMBIOS Table并解析其內容的一个功能,目前网上(在没有特别帐号权限下)能找到的资料蛮少的,所以这边会尽量用公开资料做个分析 如果還不認識SMBIOS 可以先看之前寫的文章非专业的SMBIOS笔记-程序员宅基地https://.._bmc entity manager configuration

随便推点

DBCP连接池配置详解,参数列表-程序员宅基地

文章浏览阅读9.5k次。Spring DBCP配置&amp;lt;bean id=“dataSource” class=“org.apache.commons.dbcp.BasicDataSource” destroy-method=“close”&amp;gt; &amp;lt;property name=“driverClassNa..._dbcp连接池配置详解

log 的抓取与分析_什么问题需要抓modem log-程序员宅基地

文章浏览阅读3.2k次。http://blog.csdn.net/yaoming168/article/details/38777727 log 的抓取与分析一、Android log框架简介二、log获取方式1、Eclipse 抓取1)根据信息类型过滤log那个显示框上面还有个下拉列表选项可以选择过滤哪些信息。a、Log.v 的调试颜色为黑色的,任何消息都会输出,这里的v代表verb_什么问题需要抓modem log

com.qq.ac.android,腾讯动漫(com.qq.ac.android) - 9.2.5 - 应用 - 酷安-程序员宅基地

文章浏览阅读240次。权限信息· 修改或删除您的USB存储设备中的内容· 读取您的USB存储设备中的内容· 读取手机状态和身份· 在其他应用之上显示内容· 修改系统设置· com.android.launcher.permission.READ_SETTINGS· com.android.launcher.permission.INSTALL_SHORTCUT· com.android.launcher.permiss..._qq tmf_shark

python3超简代码爬取桌面壁纸_四象限电脑壁纸-程序员宅基地

文章浏览阅读720次。 我们要爬取的是彼岸壁纸,官网是http://www.netbian.com/,不说了,上代码: for j in range(100, 120):#想爬取更多修改100 和 120数值 url = "http://www.netbian.com/desk/20" + str(j) + "-1920x1080.htm" response = requests.get(u..._四象限电脑壁纸

html-javaScript-基础及对象常用方法_javescirpt getmonth-程序员宅基地

文章浏览阅读584次。javaScript边解释 边运行网页中引用js内部引用html外部引用在head标签中引用<script src="" type="text/javascript" charset="utf-8"></script>注意:在head中外部引用了js文件 那么在body中不可以内部引用标签内引用在标签内使用需要和事件结合引用变量js没有编译报错..._javescirpt getmonth

Swift 基本数据类型与运算符表达式-程序员宅基地

文章浏览阅读96次。//// main.swift// LessonSwift01//// Created by lanouhn on 16/1/25.// Copyright 2016年 齐彦坤. All rights reserved.// import Foundation// 输出函数print("Hel..._swift 基本数据类型运算