dubbo初始化死锁

本文详细介绍了Dubbo服务在初始化过程中可能出现的死锁现象,分析了死锁的原因——服务提供者在Spring初始化期间调用getBean方法导致的线程死锁。提出了三种规避方法:避免使用applicationContext.getBeans,调整配置加载顺序,以及启用延迟加载。强调尽量利用Spring的IOC特性,避免将其变为工厂模式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明

阅读dubbo官方文档,看到初始化死锁部分,特地在此记录一番,并结合线上业务给出可能的解决方案。

死锁产生的原因

当spring解析到<dubbo:serivce />时,就已经向外暴露了服务,而spring还在初始化其他的bean,此时如果有消费者的请求进来,并且服务的提供者类中含有调用applicationContext.getBean()的用法时,那么会产生死锁。

请求线程的applicationContext.getBean()方法,会先同步singletonObjects判断bean是否存在,不存在则同步beanDefinitionMap进行初始化,并再次同步singletonObjects写入该bean;
而对于spring初始化线程来说,是不需要判断bean是否存在的,直接同步beanDefinitionMap进行初始化,并同步singletonObjects写入该bean;
此时就发生了死锁:请求线程先锁singletonObjects,再锁beanDefinitionMap,最后再锁singleObjects;而spring初始化线程先锁beanDefinitionMap,再锁singleObjects,反向锁导致线程死锁(即当需要加多把锁,但是加锁的顺序不一致时,会产生死锁),此时启动失败,无法提供服务。

(扩展:springIOC容器中有两个重要的map–beanDefinitionMap和singletonObjects,beanDefinitionMap中保存的是对bean的描述信息,即会将基于xml或者注解配置的bean转换成内部统一描述对象BeanDefinition进行存储,在创建bean时会对该对象加锁,防止篡改元数据信息;singletonObjects保存的单例对象的集合,在实例化对象时会对该对象进行加锁,防止并发修改)

规避办法

  1. 尽量不要使用applicationContext进行注入,而是采用spring IOC进行注入;毕竟不能IOC才是spring的精华,不能使spring沦落为工厂模式~
  2. 如果一定要用getBean方法,可以将dubbo配置放在最后,保证spring最后加载dubbo配置;
  3. 如果不想依赖配置之间的顺序,可以配置dubbo进行延迟加载,即<dubbo: provider delay="-1" />,目的使dubbo在spring完成初始化之后再对外暴露服务;
  4. 如果大量使用getBean,那么spring已经作为工厂模式在使用,可以将dubbo服务进行隔离单独的spring服务;
### Dubbo 客户端线程模型架构工作原理 Dubbo客户端的线程模型设计旨在高效处理远程服务调用并管理并发请求。通过自适应扩展机制,可以根据URL参数动态调整线程池配置[^1]。 #### 线程池初始化 当启动Dubbo消费者应用时,会依据配置文件或默认设置创建线程池实例。此过程涉及解析`dubbo.consumer.threadpool`属性及其关联参数,如核心线程数(`corethreads`)、最大线程数(`maxthreads`)等。这些设定直接影响后续RPC调用期间资源分配策略。 ```properties # 配置示例 dubbo.consumer.threadpool=fixed dubbo.consumer.corethreads=200 dubbo.consumer.maxthreads=1000 ``` #### 请求提交流程 每当发起一次远端方法调用(DemoService.sayHello()),实际执行路径如下: - **代理对象**接收到API接口调用后封装成Invocation对象; - 调度器根据负载均衡算法挑选合适的服务提供方节点; - 将准备好的消息体发送至目标地址前,先经过过滤链(Filter Chain)做预处理操作; - 最终由Transporter负责建立物理连接并向对方传递二进制流数据; 在此过程中,所有异步任务均交予预先构建好的ExecutorService来承担,确保主线程不会因等待响应而阻塞过久。 #### 响应回调机制 一旦网络层确认已成功送达指令包,则立即触发监听事件通知业务逻辑继续推进。此时如果启用了Future模式,则允许应用程序提前返回临时结果给前端展示,待真正完成后再更新最终状态。 对于同步场景,默认情况下将一直挂起直到获得确切答复为止。不过得益于灵活可配的超时控制选项,可以有效防止长时间无回应造成的死锁现象发生。 ```java // Java代码片段示意如何使用CompletableFuture优雅地处理异步回调 public CompletableFuture<String> asyncSayHello(String name){ return RpcContext.getContext().getCompletableFuture(); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值