Dubbo3 延遲暴露

2022-03-31 17:59 更新

延遲暴露 Dubbo 服務(wù)

如果你的服務(wù)需要預(yù)熱時間,比如初始化緩存,等待相關(guān)資源就位等,可以使用 delay 進(jìn)行延遲暴露。我們在 Dubbo 2.6.5 版本中對服務(wù)延遲暴露邏輯進(jìn)行了細(xì)微的調(diào)整,將需要延遲暴露(delay > 0)服務(wù)的倒計時動作推遲到了 Spring 初始化完成后進(jìn)行。你在使用 Dubbo 的過程中,并不會感知到此變化,因此請放心使用。

Dubbo 2.6.5 之前版本

延遲到 Spring 初始化完成后,再暴露服務(wù)(基于 Spring 的 ContextRefreshedEvent 事件觸發(fā)暴露)

<dubbo:service delay="-1" />

延遲 5 秒暴露服務(wù)

<dubbo:service delay="5000" />

Dubbo 2.6.5 及以后版本

所有服務(wù)都將在 Spring 初始化完成后進(jìn)行暴露,如果你不需要延遲暴露服務(wù),無需配置 delay。

延遲 5 秒暴露服務(wù)

<dubbo:service delay="5000" />

Spring 2.x 初始化死鎖問題

觸發(fā)條件

在 Spring 解析到 ?<dubbo:service />? 時,就已經(jīng)向外暴露了服務(wù),而 Spring 還在接著初始化其它 Bean。如果這時有請求進(jìn)來,并且服務(wù)的實現(xiàn)類里有調(diào)用? applicationContext.getBean() ?的用法。

  1. 請求線程的 applicationContext.getBean() 調(diào)用,先同步 singletonObjects 判斷 Bean 是否存在,不存在就同步 beanDefinitionMap 進(jìn)行初始化,并再次同步 singletonObjects 寫入 Bean 實例緩存。
    deadlock
  2. 而 Spring 初始化線程,因不需要判斷 Bean 的存在,直接同步 beanDefinitionMap 進(jìn)行初始化,并同步 singletonObjects 寫入 Bean 實例緩存。/user-guide/images/lock-init-context.jpg
    這樣就導(dǎo)致 getBean 線程,先鎖 singletonObjects,再鎖 beanDefinitionMap,再次鎖 singletonObjects。而 Spring 初始化線程,先鎖 beanDefinitionMap,再鎖 singletonObjects。反向鎖導(dǎo)致線程死鎖,不能提供服務(wù),啟動不了。

規(guī)避辦法

  1. 強(qiáng)烈建議不要在服務(wù)的實現(xiàn)類中有 applicationContext.getBean() 的調(diào)用,全部采用 IoC 注入的方式使用 Spring的Bean。
  2. 如果實在要調(diào) getBean(),可以將 Dubbo 的配置放在 Spring 的最后加載。
  3. 如果不想依賴配置順序,可以使用 ?<dubbo:provider delay=”-1” />?,使 Dubbo 在 Spring 容器初始化完后,再暴露服務(wù)。
  4. 如果大量使用 getBean(),相當(dāng)于已經(jīng)把 Spring 退化為工廠模式在用,可以將 Dubbo 的服務(wù)隔離單獨的 Spring 容器。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號