dubbo初始化死鎖

說明

閱讀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服務;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章