近期,在部署服务时候遇到了个概率出现的问题,pod节点health接口检查一直没有正常,但是节点又在nacos上注册成功了,导致部分接口请求出现了问题,请求会一直等待到超时,没有正常的数据返回。问题的pod节点,查看业务日志,也没有借口业务的日志。
不得已,只能先在nacos上将异常节点下线,再定位具体问题。
在pod内用arthas检查一下线程的状态,关于arthas的安装使用,见【快速入门】。
可以看到main线程和XNIO-1相关的线程都是BLOCKED状态,所以所有的请求才没有正常被处理。
然后详细看下main线程和XNIO-1线程的堆栈信息。
可以看到main线程和XNIO-1线程发生资源抢占导致了死锁。
项目中dubbo使用的是3.2.0版本,使用
thread -b 命令检测死锁可以看到其他所有XNIO-1线程都是被相同的地方阻塞的。从dubbo的GitHub上可以找到类似的issue:【dubbo3.1.5版本BUG!!!,启动是出现线程死锁导致启动服务失败】和【Dead lock in Dubbo3.1.9】,死锁的场景是类似的。都是一个线程先拿Spring的Map锁,再拿Dubbo的Deployer锁,一个线程先拿Dubbo的Deployer锁,再拿Spring的Map锁,从而导致了死锁的产生。

就是在
onApplicationEvent中,获取了全局默认的单例bean注册表的单例锁,在并发环境下,管理Spring容器的bean生命周期过程中,使用这个锁来防止数据竞争和不一致性。根据issue里面的建议,要解决该问题有三条路径:
一是对当前项目中的启动顺序进行梳理和控制,在dubbo启动完全之前不允许注册到nacos上,其他需要用到dubbo调用的自动运行方法也需要排查;
二是将dubbo升级到最新版本,在【Dead lock in Dubbo3.1.9】中,官方回复升级到最新版本解决,但升级的话需要考虑其他相关的微服务需要全部一起升级,并且需要验证升级后该问题能够解决。

三是在不修改当前项目使用的dubbo版本,也不进行完整项目启动顺序的梳理,在业务项目中,新建
org.apache.dubbo.config.spring.context 包路径,将commit中的文件拷贝进去,重新打包工程时,会将该文件覆盖编译。- 作者:Yibin
- 链接:https://yibin.dev/article/8fcaf100-ab14-439f-8b1a-7c81da767f3b
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章








