环境: spring boot3.x, druid 1.6.16, mybatis-plus 3.5.6
描述2:
内网部署服务:mysql 链接:ip:port,
测试环境买的阿里云mysql服务,阿里云mysql域名:port
现象:spring boot启动慢,druid会掉连接,连接成功后偶发性请求慢,需要5s,8s
1. 由于是内网部署的,当时我直接判断的是druid有问题,但是由于内网环境,排查问题很慢
1.1. 使用工具arthas
trace 相关命令排查
thread -n 5 排查
无果,只看到mysql驱动线程耗费慢
1.2. 怀疑mysql问题
1.2.1 在另外一台服务器新增mysql实例无果
1.2.2 增加mysql buffer pool 。让数据塞入缓存。优化无果,还是没有解决偶发慢问题
1.3. 怀疑当前机器硬件 磁盘问题
1.3.1 使用查询磁盘命令
判断为磁盘慢,是机械硬盘,非固态。但是此时我用hikari连接池,就很稳定
故此判断,虽然机械硬盘慢,但不是主因,此时排查也告一段落,替换为hikari
1.4 druid 连接串中有useSSL=true, 修改此配置,改为false, 同样没有解决问题
总结:优化点:
useSSL=false
加大buffer pool配置
新增mysql实例
暂时解决替换为hikari
转机:公司购买的阿里云mysql实例,是体验版,最近过期了。替换为了阿里云服务器创建一个实例。此时发现服务,同样出现了请求慢的问题
2.1 debug druid init方法:
2.2 找到慢方法:
2.3 进入createPhysicalConnection方法。跟踪核心慢方法createPhysicalConnection,此时碰到一个反编译一个迷惑性问题跟踪到 var29 = true; 慢,但是这个就是一个变量。最后发现可以点击进入方法,可能为idea反编译问题,
2.4 进入DruidAbstractDataSource类的createPhysicalConnection():
2.5 connect下个方法:
switch SINGLE_CONNECTION
==> ConnectionImpl.getInstance(conStr.getMainHost());
此时注意 mysql-connector-j 为9.0.0版本
2.6 继续 debug 。来到了ConnectionImpl类的getInstance方法
2.7 多次重启最终找到慢方法:
new ConnectionImpl(hostInfo) ==> inetSocketAddress.getHostName()
2.8 getHostName()为什么慢:
2.8.2 尝试禁用dns反向解析:
如果不需要反向分析主机名,可以在Java启动参数中添加 -Djava.net.preferiPv4Stack=true 参数,强制使用 IP4 地址。这样就会跳过反向解
true分析的步骤,提高获取主机名的速度。
#不起作用
java Djava.net.preferIPv4Stack=true YourApp
2.9 此时笔者我尝试跟踪另外一个服务,采用的mysql驱动为8.0.33 找到 ConnectionImpl类,并没有发现getHostName()方法,且启动速度很快。那处理方式就是将mysql驱动版本9.0.0降级为8.0.33
经过排查pom依赖 找到mybatis plus 设置的mysql-connector-j 版本为9.0.0:
3.0 解决方式:在mybatis plus pom:添加排除,再添加8.0.33
3.1 文字版:
<exclusion>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</exclusion>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
3.2 我也向 druid发起过issue,但是不是人家的问题,也没人搭理我。mybatis-plus: gitee不能发起issue, github发起issue快速被关闭,且没有被再次回复 驱动升级到9.0.0问题。好在最终通过降版本解决了问题。
mysql-connector-j 9.0.0 创建连接启动慢 · Issue #6543 · baomidou/mybatis-plus · GitHub
4. 总结:
现象:druid 启动慢,启动成功偶发请求慢,过一阵就恢复问题
原因:由于使用mysql-connector-j 9.0.0版本,其中有个方法getHostName() 触犯了反向DNS. 导致druid在mysql连接失效后,创建连接非常耗时。
也解释了当时内网不成功时,公司启用的阿里云服务实例为啥就可以问题,因为他是域名getHostName()不慢 rm-f8zjn6u6671y53f3y.mysql.rds.aliyuncs.com:3306
spring boot3 + mybatis plus 3.5.6 新版本导致。
解决方案:降级mysql驱动版本为8.0.33即可。
水平有限,上述如有错误,欢迎指正修改!感谢