dubbo2.7 49 延迟暴露
dubbo2.7 49 延迟暴露
程序员朱永胜有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步, 认准
https://blog.zysicyj.top
全网最细面试题手册,支持艾宾浩斯记忆法。这是一份最全面、最详细、最高质量的 java 面试题,不建议你死记硬背,只要每天复习一遍,有个大概印象就行了。https://store.amazingmemo.com/chapterDetail/1685324709017001`
延迟暴露 Dubbo 服务
背景
如果你的服务需要预热时间,比如初始化缓存,等待相关资源就位等,可以使用 delay 进行延迟暴露。我们在 Dubbo 2.6.5 版本中对服务延迟暴露逻辑进行了细微的调整,将需要延迟暴露(delay > 0)服务的倒计时动作推迟到了 Spring 初始化完成后进行。你在使用 Dubbo 的过程中,并不会感知到此变化,因此请放心使用。
示例
Dubbo 2.6.5 之前版本
延迟到 Spring 初始化完成后,再暴露服务 1
1 | <dubbo:service delay="-1" /> |
延迟 5 秒暴露服务
1 | <dubbo:service delay="5000" /> |
Dubbo 2.6.5 及以后版本
所有服务都将在 Spring 初始化完成后进行暴露,如果你不需要延迟暴露服务,无需配置 delay。
延迟 5 秒暴露服务
1 | <dubbo:service delay="5000" /> |
Spring 2.x 初始化死锁问题
触发条件
在 Spring 解析到 <dubbo:service />
时,就已经向外暴露了服务,而 Spring 还在接着初始化其它 Bean。如果这时有请求进来,并且服务的实现类里有调用 applicationContext.getBean()
的用法。
请求线程的 applicationContext.getBean() 调用,先同步 singletonObjects 判断 Bean 是否存在,不存在就同步 beanDefinitionMap 进行初始化,并再次同步 singletonObjects 写入 Bean 实例缓存。
而 Spring 初始化线程,因不需要判断 Bean 的存在,直接同步 beanDefinitionMap 进行初始化,并同步 singletonObjects 写入 Bean 实例缓存。
这样就导致 getBean 线程,先锁 singletonObjects,再锁 beanDefinitionMap,再次锁 singletonObjects。
而 Spring 初始化线程,先锁 beanDefinitionMap,再锁 singletonObjects。反向锁导致线程死锁,不能提供服务,启动不了。
规避办法
- 强烈建议不要在服务的实现类中有 applicationContext.getBean() 的调用,全部采用 IoC 注入的方式使用 Spring 的 Bean。
- 如果实在要调 getBean(),可以将 Dubbo 的配置放在 Spring 的最后加载。
- 如果不想依赖配置顺序,可以使用
<dubbo:provider delay=”-1” />
,使 Dubbo 在 Spring 容器初始化完后,再暴露服务。 - 如果大量使用 getBean(),相当于已经把 Spring 退化为工厂模式在用,可以将 Dubbo 的服务隔离单独的 Spring 容器。