SpringBoot Seata 死锁问题排查

这篇具有很好参考价值的文章主要介绍了SpringBoot Seata 死锁问题排查。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

SpringBoot Seata 死锁问题排查

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

SpringBoot Seata 死锁问题排查

好吧,姑且先不深究为什么本地可以启动而部署到服务器上就无法启动的问题,这个不是重点,重点是怎么让它启动起来。(PS:我猜测可能是环境不同造成的,包括操作系统不同和JDK版本不同)

遇到这种情况,我先用jstack查看堆栈情况,果然发现了死锁

SpringBoot Seata 死锁问题排查

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

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

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

可以通过 jconsole 和 jvisualvm 查看

SpringBoot Seata 死锁问题排查

需要注意,如果是查看远程进程,则需要加一些启动参数

  • -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

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

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

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

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

SpringBoot Seata 死锁问题排查

main线程持有<0x00000000c07a33d8>这个对象的锁,同时它还需要<0x00000000ff295ca8>对象的锁,而timeoutChecker_1_1线程正好相反,于是死锁了

main线程很好理解,就是我们这个SpringBoot应用的主线程,但是timeoutChecker_1_1线程是哪儿来的呢,通过分析发现它来自Seata

对了,该项目中Spring Boot版本是2.6.6,Seata版本是1.4.2

找到timeoutChecker的出处了

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

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

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

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

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

接着看1.4.2

SpringBoot Seata 死锁问题排查

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

SpringBoot Seata 死锁问题排查

所以,ExtConfigurationProvider 是 SpringBootConfigurationProvider

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

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

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

可以看到,getSingletonFactoryBeanForTypeCheck()方法里,对singletonObjects加了同步锁

凡是通过DefaultSingletonBeanRegistry#getSingleton()获取单例Bean的都会先对singletonObjects加锁

接下来看lookup

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

可以看到,NacosRegistryServiceImpl的lookup()这里也加了锁。另外,getNamingProperties()的时候由于再次用到了ConfigurationFactory.CURRENT_FILE_INSTANCE,所以又到了SpringBootConfigurationProvider#provide()

至此,Seata整个定时任务启动的主要逻辑我们都梳理完了,几处加锁的也都找到了

SpringBoot Seata 死锁问题排查

这些加锁的地方也就是容易出现死锁的地方

死锁是由于加锁顺序不一致造成的

下面看main线程启动

由于SeataDataSourceBeanPostProcessor实现了BeanPostProcessor接口,所以在创建容器之后会回调其postProcessAfterInitialization()方法

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

SpringBoot Seata 死锁问题排查

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

SpringBoot Seata 死锁问题排查

Spring启动的时候去创建Spring容器,后面就是Spring那一套

ConfigurableApplicationContext#refresh()

ServletWebServerApplicationContext#refresh()

SpringBoot Seata 死锁问题排查

不再赘述

由于需要注入依赖,所以,这个过程中肯定会多次调用 AbstractBeanFactory.getBean()

前面我们讲过,DefaultSingletonBeanRegistry.getSingleton() 时是加了锁的。因此,main线程很有可能会先持有该锁,当初始化到Seata的时候,又要获取该锁,于是出现了锁争用。

SpringBoot Seata 死锁问题排查

由于两个线程对同一资源的加锁顺序不一致,导致死锁。

由于timeoutChecker是定时任务每隔10秒启一次,所以第二次加锁顺序变成231

好了,关于main线程和timeoutChecker线程死锁的分析就先到这里了

现在,回到项目中来,由于我们的项目中有一个比较耗时的操作,超时时间固定是60秒,这个方法本来应该在Seata代理数据源之后做,不知道为什么服务器上先执行了,导致main线程等待了60秒,之后才执行SeataDataSourceBeanPostProcessor#postProcessAfterInitialization()

SpringBoot Seata 死锁问题排查

最终解决方法时将@PostConstruct注解去掉,不在容器初始化的时候取做这么耗时的操作

如果采用Seata-1.5.2版本的话,可能也不会出现死锁问题

 文章来源地址https://www.toymoban.com/news/detail-748973.html

参考

jconsole远程连接失败如何解决 - 问答 - 亿速云 (yisu.com) 

https://www.zhihuclub.com/179001.shtml 

https://zhuanlan.zhihu.com/p/619203844

 

到了这里,关于SpringBoot Seata 死锁问题排查的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring | 基于SpringBoot的多数据源实战 - 使用seata实现多数据源的全局事务管理

    在软件开发中, 多数据源 的应用越来越普遍,特别是在 微服务架构 和 业务模块化 的场景下。多数据源能够让不同的业务模块和微服务拥有各自独立的数据存储,大大提高了系统的灵活性和可维护性。本文将深入探讨多数据源的配置和实施,以及在 Spring Boot 环境下,如何通

    2024年02月07日
    浏览(51)
  • 死锁的排查工具有哪些?

    死锁是多线程编程中常见的问题,可以使用多种工具和技术来排查和分析死锁问题。以下是一些常用的死锁排查工具和方法: JConsole 和 JVisualVM: 这些是Java自带的监控工具,可以用于监视Java应用程序的运行状态。通过查看线程状态和堆栈信息,可以识别是否存在死锁,并尝

    2024年02月09日
    浏览(31)
  • 【mysql并行批量删除死锁排查】

    mysql批量删除并插入新数据的场景下,为提高执行效率,使用了多线程并发执行的方式。当然mysql建表时使用了分区(partition)机制,聚焦到我们这次讨论的问题,分区(partition)以及跟案例无关的内容暂且不提。 测试环境并发量不高,简单验证执行ok,预发环境并发量比较高

    2024年02月13日
    浏览(36)
  • Seata TCC 模式下解决幂等、悬挂、空回滚问题 | Spring Cloud56

    通过以下系列章节: docker-compose 实现Seata Server高可用部署 | Spring Cloud 51 Seata AT 模式理论学习、事务隔离及部分源码解析 | Spring Cloud 52 Spring Boot集成Seata利用AT模式分布式事务示例 | Spring Cloud 53 Seata XA 模式理论学习、使用及注意事项 | Spring Cloud54 Seata TCC 模式理论学习、生产级

    2024年02月09日
    浏览(24)
  • 【MySQL】数据库排查慢查询、死锁进程排查、预防以及解决方法

    1.1检查慢查询日志是否开启 1.1.1使用命令检查是否开启慢查询日志: 如果是 Value 为 off 则并未开启 1.1.2开启并且查看慢查询日志: MySQL提供了慢查询日志功能,可以记录所有执行时间超过long_query_time秒的查询语句,通过分析这些慢查询可以找到数据库性能瓶颈。 启用慢查询日志

    2024年03月19日
    浏览(75)
  • 【工作中问题解决实践 九】Spring中事务传播的问题排查

    最近在工作中遇到了三个关于事务操作的问题,顺便就着这三个问题又回顾了一遍Spring的事务相关的操作,想着一次性把这个问题研究明白了,后续使用事务的时候也能踏实点,让事务发挥真实的作用 什么是事务? 事务就是把一系列的动作当成一个独立的工作单元,这些动

    2024年02月14日
    浏览(31)
  • d-link路由器经常出现断线与死机现象的排查及解决方法

    路由器经常出现断线现象解决办法 1.确认外线有无问题,不接路由器直接连接调制解调器会不会掉线; 2. 检查是PC是否有感染病毒的情况,如有,请尽快处理; 3.检查是否有人在使用BT,或者是迅雷,电驴等P2P的软件在下载,如有,建议先试下不做下载是否就能稳定。在P2P软件里

    2024年02月06日
    浏览(32)
  • springboot应用,cpu高、内存高问题排查

    前几天,排查了2个生产问题。一个cpu高,一个内存高。今天把解决过程整理一下 先说cpu高的这个问题 新系统,上线半年,一直比较稳定。有一天,运维过来说:cpu有点高,超过80%了。这个系统的量没有那么大,也没有什么很复杂的计算任务。cpu不应该这么高。 1.1、获取栈日

    2024年02月19日
    浏览(23)
  • Spring中@Value注解取值为null问题排查

    一、背景 近期应用中因业务迭代需要接入 user 客户端,接入后总是启动失败,报注册 user bean 依赖的配置属性为 null(如 appName,group 等都为空),示例代码如下: 二、@Value 取值为 null 原因分析 2.1. @Value 取值为 null 常见原因分析 常见现象一:类没有交给 Spring 管理,比如类没

    2024年02月10日
    浏览(29)
  • springboot git配置文件自动刷新失败问题排查

    ​​​​​​​http://{ip}:{port}/refresh 刷新配置接口如上  说明:当前项目springBoot版本是1.5.9,接口路径与2.x不同 路径区别:/refresh  VS / actuator/refresh 用postman调用refresh接口刷新git配置,报错如下,没有权限 在服务本地启动,调用refresh接口,日志如下: 2024-01-08 15:18:25.663 [IN

    2024年01月22日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包