SpringBoot Seata 死锁问题排查
现象描述:Spring Boot项目,启动的时候卡住了,一直卡在那里不动,没有报错,也没有日志输出

但是,奇怪的是,本地可以正常启动

好吧,姑且先不深究为什么本地可以启动而部署到服务器上就无法启动的问题,这个不是重点,重点是怎么让它启动起来。(PS:我猜测可能是环境不同造成的,包括操作系统不同和JDK版本不同)
遇到这种情况,我先用jstack查看堆栈情况,果然发现了死锁

拿到jstack的完整信息,然后仔细排查,看不懂的话也可以借助工具


分析了每个被阻塞的线程之后,发现main线程和timeoutChecker_1_1互相等待对方持有的锁,从而形成了死锁
可以通过 jconsole 和 jvisualvm 查看

需要注意,如果是查看远程进程,则需要加一些启动参数
- -Dcom.sun.management.jmxremote:启用JMX
- -Dcom.sun.management.jmxremote.port=<端口号>:指定JMX远程连接的端口号
- -Dcom.sun.management.jmxremote.authenticate=false:禁用JMX远程连接的认证
- -Dcom.sun.management.jmxremote.ssl=false:禁用JMX远程连接的SSL加密
于是,我又重启启动
java -jar -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9099 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false app.jar
通过jps或者ps命令查找应用的pid





用jvisualvm查看也可以,不再赘述,结果都是一样的


好了,工具介绍到此为止,下面重点看代码

main线程持有<0x00000000c07a33d8>这个对象的锁,同时它还需要<0x00000000ff295ca8>对象的锁,而timeoutChecker_1_1线程正好相反,于是死锁了
main线程很好理解,就是我们这个SpringBoot应用的主线程,但是timeoutChecker_1_1线程是哪儿来的呢,通过分析发现它来自Seata
对了,该项目中Spring Boot版本是2.6.6,Seata版本是1.4.2
找到timeoutChecker的出处了



延迟60秒启动定时任务,每隔10秒执行一次,调用io.seata.core.rpc.netty.NettyClientChannelManager#reconnect()


记住这一行,首先调用RegistryFactory.getInstance()获取一个RegistryService,然后调用RegistryService对象的lookup()方法


接着看1.4.2

最重要的是 EnhancedServiceLoader.load(ExtConfigurationProvider.class).provide(configuration);

所以,ExtConfigurationProvider 是 SpringBootConfigurationProvider



回到seata-1.4.2,可以看到这里调用了applicationContext.getBean(),于是DefaultListableBeanFactory.getBean()





可以看到,getSingletonFactoryBeanForTypeCheck()方法里,对singletonObjects加了同步锁
凡是通过DefaultSingletonBeanRegistry#getSingleton()获取单例Bean的都会先对singletonObjects加锁
接下来看lookup


可以看到,NacosRegistryServiceImpl的lookup()这里也加了锁。另外,getNamingProperties()的时候由于再次用到了ConfigurationFactory.CURRENT_FILE_INSTANCE,所以又到了SpringBootConfigurationProvider#provide()
至此,Seata整个定时任务启动的主要逻辑我们都梳理完了,几处加锁的也都找到了

这些加锁的地方也就是容易出现死锁的地方
死锁是由于加锁顺序不一致造成的
下面看main线程启动
由于SeataDataSourceBeanPostProcessor实现了BeanPostProcessor接口,所以在创建容器之后会回调其postProcessAfterInitialization()方法









所以,最终还是调NettyClientChannelManager#reconnect()

Spring启动的时候去创建Spring容器,后面就是Spring那一套
ConfigurableApplicationContext#refresh()
ServletWebServerApplicationContext#refresh()

不再赘述
由于需要注入依赖,所以,这个过程中肯定会多次调用 AbstractBeanFactory.getBean()
前面我们讲过,DefaultSingletonBeanRegistry.getSingleton() 时是加了锁的。因此,main线程很有可能会先持有该锁,当初始化到Seata的时候,又要获取该锁,于是出现了锁争用。

由于两个线程对同一资源的加锁顺序不一致,导致死锁。
由于timeoutChecker是定时任务每隔10秒启一次,所以第二次加锁顺序变成231
好了,关于main线程和timeoutChecker线程死锁的分析就先到这里了
现在,回到项目中来,由于我们的项目中有一个比较耗时的操作,超时时间固定是60秒,这个方法本来应该在Seata代理数据源之后做,不知道为什么服务器上先执行了,导致main线程等待了60秒,之后才执行SeataDataSourceBeanPostProcessor#postProcessAfterInitialization()

最终解决方法时将@PostConstruct注解去掉,不在容器初始化的时候取做这么耗时的操作
如果采用Seata-1.5.2版本的话,可能也不会出现死锁问题
相关文章:
SpringBoot Seata 死锁问题排查
现象描述:Spring Boot项目,启动的时候卡住了,一直卡在那里不动,没有报错,也没有日志输出 但是,奇怪的是,本地可以正常启动 好吧,姑且先不深究为什么本地可以启动而部署到服务器上就无…...
文章解读与仿真程序复现思路——电力系统自动化EI\CSCD\北大核心《考虑两阶段鲁棒优化配置的多微网合作博弈》
这个标题涉及到多个概念,让我们逐步解读: 考虑两阶段鲁棒优化配置: 两阶段: 指的是在解决问题或进行优化时,可能存在两个不同的阶段或步骤。这表明问题的解决不是一步完成的,而是需要经过多个步骤或阶段。鲁…...
Redis常见类型
常用类型String字符串类型Hash字典类型List列表类型Set集合类型ZSet有序集合类型 Java程序操作Redis类型代码操作Redis 常用类型 String字符串类型 使用方式: 使用场景: Hash字典类型 字典类型(Hash) 又被成为散列类型或者是哈希表类型࿰…...
深入了解数据库锁:类型、应用和最佳实践
目录 1. 引言 2. 数据库锁的基本概念 2.1 悲观锁和乐观锁 2.2 排他锁和共享锁 3. 悲观锁的应用场景 3.1 长事务和大事务 3.2 并发修改 3.3 数据库死锁 4. 悲观锁的最佳实践 4.1 精细控制锁的粒度 4.2 避免死锁 4.3 考虑乐观锁 5. 案例分析 5.1 银行系统的转账操作…...
python3.5安装教程及环境配置,python3.7.2安装与配置
大家好,小编来为大家解答以下问题,python3.5安装教程及环境配置,python3.7.2安装与配置,现在让我们一起来看看吧! python 从爬虫开始(一) Python 简介 首先简介一下Python和爬虫的关系与概念&am…...
ubuntu安装tomcat并配置前端项目
1.1查找 # 先更新 sudo apt update # 查找 apt search jdk1.2安装 sudo apt install openjdk-8-jdk1.3验证 java -version 2.安装tomcat 下载链接:Apache Tomcat - Apache Tomcat 8 Software Downloadshttps://tomcat.apache.org/download-80.cgi下载这个&…...
GeoPandas初体验:它是什么,我用它展示一下shp矢量数据
GeoPandas 是一个开源的 Python 库,用于处理地理空间数据。它扩展了 Pandas 这个流行的 Python 数据操作库,增加了对地理数据类型和操作的支持。GeoPandas 结合了 Pandas、Matplotlib 和 Shapely 的功能,提供了一个易于使用且高效的工具&…...
Python-滑雪大冒险【附源码】
滑雪大冒险 《滑雪大冒险》是一款充满趣味性和挑战性的休闲竞技游戏,在游戏中,玩家将扮演一位勇敢的滑雪者,在雪山上展示他们的滑雪技巧,游戏采用2D图形界面,以第三人称视角呈现 运行效果:用方向键及方向键…...
Linux---日志管理
本章主要介绍Linux中的日志管理 了解rsyslog是如何管理日志的查看日志的方法 日志管理简介 工作当中的日志,特指硬件和软件的日志,管理员可以通过它来检查错误发生的原因,或者寻找受到攻击时攻击者留下的痕迹。日志管理包括管理系统日志、应…...
Java高级技术-单元测试
单元测试 Junit单元测试框架 Junit单元测试-快速入门 方法类 测试类 Junit框架的基本注解...
springboot集成邮箱验证功能
准备工作 开启SMTP服务 前往你的邮箱网站,以网易邮箱为例,打开网易邮箱地址,登录你的邮箱,进入邮箱管理后台界面。点击“设置”》》“POP3/SMTP/IMAP”后,点击开启SMTP服务即可。 技术实现 Spring Boot 发送邮件验证…...
HarmonyOS应用程序框架——UIAbility实操
UIAbility概述 UIAbility是一种包含用户界面的应用组件,主要用于和用户进行交互。UIAbility也是系统调度的单元,为应用提供窗口在其中绘制界面。 每一个UIAbility实例,都对应于一个最近任务列表中的任务。 一个应用可以有一个UIAbility&…...
数实融合!低代码推动工业数字化转型走“深”向“实”
当下,“数字化、智能化”已经不再是新鲜词。毕竟,在早几年前就已经有企业喊出大举进军数字化的口号,轰轰烈烈的数字化转型运动也持续了很长一段时间,有一些业内人士甚至判断“如今的企业数字化已经走过了成熟期,来到了…...
OpenGL学习资料
1.学习网站 Song Ho Ahn LearnOpenGL GAMES101:现代计算机图形学入门 OpenGL 官网 2.书籍 Fundamentals of computer graphics OpenGL ES 3.0编程指南 计算机图形学(OpenGL版)第3版 3.参考的一些文章 颜色缓冲区 深度缓冲 VBO,VAO和EBO详解 深入探索透视投影变…...
字符串指令集
字符串指令的格式 例子1就成功发送了指令 例子2就是发送的字符串有误 查询当前位置就会在附加信息中返回当前座位的坐标 第一个指令的参数就是闪灯的两个参数 如第一个示例就是10ms On Time 第二个就是Off Time 使用标准库来接收字符串命令 字符串指令的接收 因为一个指令就是…...
行云海CMS SQL注入漏洞复现
0x01 产品简介 行云海cms是完全开源的一套CMS内容管理系统,简洁,易用,安全,稳定,免费。 0x02 漏洞概述 行云海cms中ThinkPHP在处理order by排序时可利用key构造SQL语句进行注入,LtController.class.php中发现传入了orderby未进行过滤导致sql注入。攻击者除了可以利用 SQL 注入…...
窗口函数之 first_value() 和 last_value()
这次,我要从**last_value()**开始写! last_value() 众所周知,first_value() 和 last_value() 的作用是返回窗口中某个字段的第一行的值和最后一行的值。 但是在应用的时候,突然发现使用last_value() 返回了不止一条数据&#x…...
习题练习讲解
前言:这又是一个新坑,算上之前的4个坑这是第五个坑(1、C/C的讲解,2、C语言小游戏,3、大学生活,4、假哲家因为某些原因没GS),这个就是发一些自己在刷题的过程中遇到自己感觉还不错的习…...
C++STL的string模拟实现
文章目录 前言string的成员变量成员函数构造函数拷贝构造赋值重载 模拟实现string各种接口print迭代器普通迭代器const迭代器 string比较大小push_backinsert 和 eraseinserterase reserve和resizereserveresize swapfindcout和cincoutcin 前言 今天要讲string的底层实现&…...
基于ZLMediaKit的webrtc实时视频传输demo搭建
环境 ubuntu 20.04 gcc version 9.4.0 cmake version 3.16.3 部署ZLMediaKit流媒体服务器 安装openssl 首先可以检查一下自己的openssl的版本如果是1.1.1以上就可以忽略这一步 wget https://www.openssl.org/source/openssl-1.1.1k.tar.gz tar -xvzf openssl-1.1.1k…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...
