修复seata的HikariCP中加载驱动程序类的问题


文章目录

  • 引言
  • 问题引入
  • 问题分析
    • 在druid时
    • 在Hikari时
  • 问题解决
  • 总结

引言

大家好!今天我们一起探讨一下一个在seata 2.5.0版本修复的小bug,如标题所言,是和数据库连接池有关的驱动加载有关的问题,让我们一起来看看吧。

问题引入

在之前的代码中,如果连接池使用的是druid,那就完全没有问题,如果使用的是Hikari,就会报错。

示例seata服务端配置如下:

server:port:8091spring:application:name:seata-servermain:web-application-type:nonelogging:config:classpath:logback-spring.xmlfile:path:${log.home:${user.home}/logs/seata}seata:config:# support: nacos, consul, apollo, zk, etcd3type:fileregistry:# support: nacos, eureka, redis, zk, consul, etcd3, sofatype:filestore:# support: file 、 db 、 redis 、 raftmode:dbsession:mode:dblock:mode:dbdb:# If use druid, it is OK. If change to hikari, and then threw an error.datasource:hikaridb-type:mysqldriver-class-name:com.mysql.cj.jdbc.Driverurl:jdbc:mysql://localhost:3396/db_seata?useUnicode=true&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=trueuser:admin_seatapassword:123456min-conn:10max-conn:100global-table:global_tablebranch-table:branch_tablelock-table:lock_tabledistributed-lock-table:distributed_lockvgroup-table:vgroup_tablequery-limit:1000max-wait:5000druid:time-between-eviction-runs-millis:120000min-evictable-idle-time-millis:300000test-while-idle:truetest-on-borrow:falsekeep-alive:falsehikari:idle-timeout:600000keepalive-time:120000max-lifetime:1800000validation-timeout:5000# server:# service-port: 8091 #If not configured, the default is '${server.port} + 1000'

如果我使用它datasource: hikari,则会抛出错误

Caused by: java.lang.RuntimeException: Failed to load driver class com.mysql.cj.jdbc.Driver in either of HikariConfig class loader or Thread context classloader

从报错很容易看出来就是连接池初始化时无法加载MYSQL的驱动类。

问题分析

既然issue里面说到使用druid是正常的,而使用HikariCP则不行。肯定这两个进行加载驱动时有所不同。

在druid时

在seata的DruidDataSourceProvider可以看到下面的代码,Druid 正确使用了这个类加载器:setDriverClassLoader(getDriverClassLoader()),所以druid是正常加载驱动的

DruidDataSourceds=newDruidDataSource();ds.setDriverClassName(getDriverClassName());//这里明显加载了数据员的驱动类ds.setDriverClassLoader(getDriverClassLoader());ds.setUrl(getUrl());ds.setUsername(getUser());ds.setPassword(getPassword());ds.setInitialSize(getMinConn());ds.setMaxActive(getMaxConn());ds.setMinIdle(getMinConn());ds.setMaxWait(getMaxWait());

在Hikari时

在seata的HikariDataSourceProvider可以看到下面的代码,可以看到,并没有加载到驱动, 但 HikariConfig 类没有setDriverClassLoader方法,所以 Hikari 无法使用专门的类加载器,导致 Hikari 使用默认类加载器无法找到 MySQL 驱动

HikariConfigconfig=newHikariConfig(properties);config.setDriverClassName(getDriverClassName());config.setJdbcUrl(getUrl());config.setUsername(getUser());config.setPassword(getPassword());

问题解决

经过分析我们可以知道,由于Hikari的设计局限性,我们并不能将驱动直接注册在config里面,难道我们就不能解决这个问题了吗?当然不是,解决方法总是有的。

一般我们要知道,HikariCP 在设置driverClassName时,会尝试通过以下两种 ClassLoader 加载驱动类:

  1. HikariConfig 所在的 ClassLoader
  2. 当前线程的上下文 ClassLoader(Thread Context ClassLoader)

如果两者都找不到com.mysql.cj.jdbc.Driver类,就会抛出这个异常

清楚这个点之后,我们可以尝试解决这个问题。
在seata的所有provider的抽象父类中提供了获取目标驱动的方法

protectedClassLoadergetDriverClassLoader(){returnDRIVER_LOADERS.getOrDefault(getDriverClassName(),this.getClass().getClassLoader());}

我们可以采用一种“保护现场、恢复现场”的典型设计模式,在有关多线程场景经常使用。

我们先通过抽象父类获得目标驱动与驱动名,然后获取当前线程上下文原驱动,再将当前线程的驱动设置成我们第一个获取到的目标驱动并显式注册,确保类加载发生在正确的 ClassLoader 上下文中,最后finally还原线程驱动即可。

seata通过显式加载类和注册驱动到DriverManager,后续驱动实例都会存在在DriverManagergetConnection(...)就能用这个实例

HikariConfigconfig=newHikariConfig(properties);// Get the correct class loaderClassLoaderdriverClassLoader=getDriverClassLoader();StringdriverClassName=getDriverClassName();// Set driver class name in the correct class loader contextClassLoaderoriginalClassLoader=Thread.currentThread().getContextClassLoader();try{Thread.currentThread().setContextClassLoader(driverClassLoader);// 1. Explicitly load and register the drivertry{Class<?>driverClass=Class.forName(driverClassName,true,driverClassLoader);Driverdriver=(Driver)driverClass.newInstance();DriverManager.registerDriver(newDriverWrapper(driver));}catch(Exceptione){logger.warn("Failed to explicitly register driver {}",driverClassName,e);}// 2. Set configurationconfig.setDriverClassName(driverClassName);config.setJdbcUrl(getUrl());config.setUsername(getUser());config.setPassword(getPassword());}finally{Thread.currentThread().setContextClassLoader(originalClassLoader);}

总结

  1. 绕过 HikariCP 的自动类加载机制
    Seata 不依赖 HikariCP 自己去加载driverClassName,而是提前手动加载并注册 Driver
  2. 确保类加载发生在正确的 ClassLoader 上下文中
    通过Thread.currentThread().setContextClassLoader(driverClassLoader),使得后续config.setDriverClassName(...)调用时,HikariCP 内部使用的上下文 ClassLoader 正是能加载驱动的那个。
  3. DriverWrapper 保证后续 getConnection() 使用正确驱动
    即使 DriverManager 中有多个 Driver,包装后的 Driver 也能确保使用我们显式加载的那个实例,避免 ClassLoader 混乱

还有其他问题欢迎评论区友好讨论❤️

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1125998.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Python+Django+SSM旅游数据分析与推荐系统(源码+LW+调试文档+讲解等)/旅游数据挖掘/旅游数据研究/旅游分析系统/旅游推荐技术/旅游数据分析工具/旅游推荐算法

博主介绍 &#x1f497;博主介绍&#xff1a;✌全栈领域优质创作者&#xff0c;专注于Java、小程序、Python技术领域和计算机毕业项目实战✌&#x1f497; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅&#x1f447;&#x1f3fb; 2025-2026年最新1000个热门Java毕业设计选题…

基于SpringBoot+Vue的教师工作量管理系统管理系统设计与实现【Java+MySQL+MyBatis完整源码】

&#x1f4a1;实话实说&#xff1a;用最专业的技术、最实惠的价格、最真诚的态度服务大家。无论最终合作与否&#xff0c;咱们都是朋友&#xff0c;能帮的地方我绝不含糊。买卖不成仁义在&#xff0c;这就是我的做人原则。摘要 随着高等教育规模的不断扩大&#xff0c;教师工作…

实测10款好用的在线简历制作工具,一键生成专业简历

在线简历工具真的能省时间吗&#xff1f;我实测了 10 款后&#xff0c;给你一份靠谱清单 很多人做简历时会陷入两个极端&#xff1a; 要么在 Word 里反复调格式&#xff0c;要么一味追求“模板好看”。 但真正高效的方式&#xff0c;其实是&#xff1a; 用合适的在线工具&…

Google Play新开发者账号红利来了!2026年的第一桶金准备好了吗?

刚过去的2025年&#xff0c;Google Play在安全合规与开放生态之间做出了重大权衡与调整&#xff0c;一系列核心政策的收紧&#xff0c;曾导致不少用户损失开发者账号。庆幸的是自2025年12月以来&#xff0c;Google Play政策似有松动迹象&#xff0c;并传来一波利好&#xff1a;…

1天极速获取企业邓白氏编码,抢占出海业务先机!

对于正在或计划拓展海外市场的企业而言&#xff0c;邓白氏编码如同国际商业领域的“护照”和“身份证”&#xff0c;是企业进行国际贸易、参与国际招标、入驻海外平台的重要通行证。但标准申请流程长达30天&#xff0c;这一时间窗口足以让企业错失千万级订单。 我们提供的邓白氏…

认监委推荐|招投标加分资质清单:ISO/ITSS/CMMI等五大类认证详解

经常参与招投标的企业肯定会在标书中看到各种认证以及资质的加分项&#xff0c;但是各行各业各体系&#xff0c;各体系又各不相同&#xff0c;每一项体系认证的用处不仅为投标加分&#xff0c;更可为企业未来发展打下坚实基础。 那么如何为企业匹配到最适合的资质认证&#xf…

欧盟碳关税(CBAM)开始堵漏洞!多项调整方案集中公布,对中国影响有多大?

自2026年1月1日起&#xff0c;这项全球首个跨境碳关税制度将结束为期两年多的过渡期&#xff0c;正式迈入实施阶段。根据已通过的简化方案&#xff0c;进口商首次为2026年进口产品购买CBAM证书&#xff08;即“付费”&#xff09;的义务将始于2027年2月。 12月17日&#xff0c;…

搭载双(单)通道测温模组的智能抽油烟机应用方案

在现代化厨房场景中&#xff0c;抽油烟机作为核心设备&#xff0c;其性能优化与智能化升级对提升烹饪体验、保障厨房安全至关重要。LMW-MT-DFWA1(双通道)与SWA1(单通道)油烟机专用测温模组&#xff0c;凭借高精度、及快速响应&#xff0c;为抽油烟机赋予了风机启停智能控制、风…

2026年云监控工具推荐,利用云监控实现高效运维

随着企业加速云战略落地&#xff0c;跨AWS、Azure、Google Cloud、混合环境及私有云的应用、基础设施与资源管理复杂度呈指数级攀升。传统监控方案难以适配动态扩展、分布式服务、容器化工作负载及实时洞察需求&#xff0c;云监控工具由此成为企业运维的核心支撑&#xff0c;其…

跑通 Hello World 之后,我第一次真正用懂了 ESP32 的 menuconfig 和日志系统

跑通 Hello World 之后&#xff0c;我是怎么第一次真正用上 ESP32 的 menuconfig 和日志系统的 hello_world 跑通那天&#xff0c;我其实挺开心的。 程序能烧进去&#xff0c;串口能正常打印&#xff0c;一切看起来都很顺利。 但也正是在这一步之后&#xff0c;我开始意识到一个…

Sentieon软件发布V202503.02版本

一、Sentieon最新版本V202503.02 Sentieon团队持续优化升级产品&#xff0c;现已发布V202503.02版本。本文将详细介绍此次更新中的新功能和问题修复&#xff0c;以帮助您更好地了解和使用Sentieon最新版本。 图1 Sentieon V202503.02版手册目录 二、下载链接 新版本的Sentieon…

毅硕HPC | InfiniBand网络在HPC集群中的核心应用

一、引言&#xff1a; HPC 离不开 InfiniBand网络是高性能计算集群的“神经系统”——它决定了计算资源的协同效率、应用的可扩展性&#xff0c;以及最终的科学发现速度。在众多网络技术中&#xff0c;InfiniBand&#xff08;IB&#xff09;凭借其超低延迟、高带宽和硬件级卸载…

AgentRun 实战:快速构建 AI 舆情实时分析专家

舆情分析是企业感知市场脉搏、预警公关危机的“听诊器”&#xff0c;然而传统的舆情分析系统更像是一个个“手工作坊”&#xff0c;面临数据收集效率低、分析深度不够、实时性差等问题&#xff0c;经常反馈之后&#xff0c;等企业拿到报告时&#xff0c;舆论热点早已转移&#…

“十四五”国产工业软件政策落地:ZWPD在流程工业的实践与探索

工业软件是制造业数字化转型的核心支撑&#xff0c;更是保障产业链供应链安全的关键基础。“十四五”规划明确提出“突破核心工业软件”“推进工业软件国产化替代”的发展目标&#xff0c;一系列配套扶持政策相继出台&#xff0c;为国产工业软件发展注入强劲动力。流程工业作为…

Llama 是开源的,但为什么?

原文&#xff1a;towardsdatascience.com/llama-is-open-source-but-why-3f87d290d0d5?sourcecollection_archive---------5-----------------------#2024-06-25 观点 Meta 开源大模型战略分析 https://haifeng-jin.medium.com/?sourcepost_page---byline--3f87d290d0d5---…

OLAP助力大数据:实现快速决策的秘诀

OLAP助力大数据&#xff1a;实现快速决策的秘诀关键词&#xff1a;OLAP、大数据分析、多维数据、快速决策、商业智能摘要&#xff1a;在数据爆炸的今天&#xff0c;企业如何从海量数据中快速“挖”出决策所需的关键信息&#xff1f;OLAP&#xff08;联机分析处理&#xff09;正…

SpringBoot+Vue 甘肃非物质文化网站管理平台源码【适合毕设/课设/学习】Java+MySQL

&#x1f4a1;实话实说&#xff1a; 有自己的项目库存&#xff0c;不需要找别人拿货再加价&#xff0c;所以能给到超低价格。 摘要 在全球化与数字化快速发展的背景下&#xff0c;非物质文化遗产的保护与传承显得尤为重要。甘肃作为中国西北地区文化资源丰富的省份&#xff0c…

这是一份简洁实用的 CSS 开发速成手册

好的&#xff0c;这是一份简洁实用的 CSS 开发速成手册&#xff0c;涵盖核心概念和常用技巧&#xff1a;一、 基础概念选择器作用&#xff1a;指定哪些 HTML 元素应用样式。常见类型&#xff1a;元素选择器&#xff1a;p { ... } (选择所有 <p> 元素)类选择器&#xff1a…

cat /proc/interrupts 验证nvme 中断聚合

最近做了一次实验 用cat /proc/interrupts 抓取nvme的中断次数 &#xff0c;来验证开启了中断聚合后&#xff0c;中断次数是否会减少 1 首先我们先看下盘的默认值是多少 [debian~]#nvme get-feature /dev/nvme9 -f 0x7 -H #查看支持的最大队列 get-feature:0x7 (Number of Que…

大数据分析中的文本挖掘:非结构化数据决策

大数据分析中的文本挖掘:非结构化数据决策 关键词:文本挖掘、非结构化数据、自然语言处理、情感分析、主题建模、词嵌入、决策支持 摘要:本文深入探讨大数据分析中文本挖掘技术的核心原理和应用。我们将从非结构化数据的特点出发,逐步解析文本挖掘的关键技术流程,包括文本…