成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

朝花夕拾---dubbo源碼分析-創(chuàng)新互聯

前言

該篇博客意在做dubbo啟動調用流程做源碼分析,采用先給出部分結論,然后推導出整個調用流程的過程

創(chuàng)新互聯公司專業(yè)為企業(yè)提供李滄網站建設、李滄做網站、李滄網站設計、李滄網站制作等企業(yè)網站建設、網頁設計與制作、李滄企業(yè)網站模板建站服務,十載李滄做網站經驗,不只是建網站,更提供有價值的思路和整體網絡服務。一? 服務發(fā)布

dubbo服務的每個標記了@service的類和在xml配置中帶有標簽,均會被解析成ServiceBean,服務發(fā)布的故事就從serviceBean這個類開始

首先看一下serviceBean的類繼承關系:

從類繼承圖中,我們發(fā)現了幾個重要的接口:

serviceConfig? ? ? ?這個是和dubbo服務發(fā)布相關的

ApplicationListener? ? spring的事件相關

InitializingBean? ? ? ?初始化相關

當然最重要的就是ApplicationListener的監(jiān)聽方法了:

以下是服務發(fā)布的幾個重要路徑:

ServiceBean#export();

ServiceConfig#doExport()

doExportUrlsFor1Protocol()

在doExportUrlsFor1Protocol這里就是服務發(fā)布的重點了

以上截圖就是dubbo在做服務發(fā)布的核心代碼了,這里dubbo使用了動態(tài)代理(SPI)+裝飾器模式,完整的構造了一個Invoker和Exporter

DUBBO的SPI:ExtensionLoader? 通過加載指定路徑下,配置的key-value形式的類。同時還支持代理和增強(Wrapper + 裝飾),有興趣的同學可以認真研究一下dubbo的SPI機制,這里只做簡單概括,比如里面2個最重要的代理對象:proxyFacotory,protocol,他們的源碼分別截圖如下:

proxyFactory:

protocol:

從以上截圖不難發(fā)現:protocol和proxyFactory的處理邏輯大體類似:通過url獲取指定參數,如果為空,就使用默認值:然后通過ExtensionLoader加載從url中獲取的對象

首先看一下通過proxyFactory獲取的Invoker對象:

想一下,為什么extName是javassist,獲取到的ProxyFactory卻是:StubProxyFactoryWrapper?按照之前說的SPI機制,應該獲取的是:JavassistProxyFactory?

這是因為:在ExtensionLoader#createExtension時

cachedWrapperClasses的寫入是在讀取指定路徑的文件時寫入的,通過判斷加載的類是否有,包含相同接口的構造器做判斷的:

這里真正干活的還是:JavassistProxyFactory

所以,真正構建Invoker的代碼如下:

其實就是構建了一個AbstractProxyInvoker,其中的Wrapper簡單的理解成一個包裝類即可(這就是dubbo動態(tài)生成類的方式,其實沒有什么多大的技術問題,只是覺得就是裝X而已),代碼如下:

再來看看export過程:

同樣的,extName是registry,實際的加載類是:ProtocolListenerWrapper

而ProtocolListenerWrapper里面包裝的protocol是:ProtocolFilterWrapper,而ProtocolFilterWrapper里面包裝的protocol是RegistryProtocol(真正干活的)

可以看下最終生成的Exporter的結構:

其中DubboExporter是在DubboProtocol類中構造的,還是和之前一樣,通過裝飾器,一層一層遞進構造的:

至此,服務的發(fā)布已經完成,其中有些步驟跳躍可能稍微大一點,感興趣的同學請自行本地調試?

二? 服務調用

dubbo中每一個標記了@Reference域和在xml中配置了的元素,均會被解析成一個ReferenceBean

首先,看一下ReferenceBean的類關系:

其中FactoryBean就是spring的工廠Bean,和ServiceBean類似,ReferenceBean也繼承一個Config類,如上,服務調用的故事就從ReferenceConfig的#get()開始

ReferenceBean#getObject()

? ReferenceConfig#get()

init();

相信使用過動態(tài)代理的同學都知道,使用動態(tài)代理的使用,通過代理對象,在自己的邏輯里面就可以"為所欲為"了。dubbo在服務調用的時候也是這么干的!

init方法就是創(chuàng)建代理的入口,方法比較長,咱們撿重點說,前面就是一些校驗,判斷,最主要的方法入口:

創(chuàng)建代理需要一個map,看看這個map里面的信息如下:

下面正式開啟創(chuàng)建代理的過程,老規(guī)矩,忽略掉無關精要的代碼,直接上干貨:

這個refprotocol就是在前面截圖的那個Protocol$Adaptive代碼,這里咱們?yōu)榱朔奖阏{試,直接把代碼替換一下:

和服務發(fā)布過程一樣,extName是registry,獲取到的實例卻是:ProtocolListenerWrapper(裝飾器模式)

大概裝飾層級就是:

ProtocolListenerWrapper

?ProtocolFilterWrapper

RegistryProtocol

在RegistryProtocol是真正干活的地方:

一路debug調試,最終返回到創(chuàng)建代理的代碼入口:

在之前的服務發(fā)布過程中,我們已經帖出了proxyFactory的相關代碼(dubbo這里做了動態(tài)加載,不利于調試,咱們做個替換)

替換后的代碼如下:

現在將要進行真正的動態(tài)代理的創(chuàng)建過程:

和其他的Adaptive一樣,真正干活的是JavassistProxyFactory,使用StubProxyFactoryWrapper做裝飾

真正干活的是JavassistProxyFactory

看到這里,熟悉動態(tài)代理的同學已經很熟悉了。真正的執(zhí)行邏輯就在InvokerInvocationHandler里面了,在這個handler里面是不是為所欲為呢?

截圖如下:

由截圖可知,在InvokerInvocationHandler里面真正調用就是使用invoker調用邏輯

當真正調用時,一路dubug

這個Invoker也是一個裝飾器。咱們一步一步調試進入:

首先:MockClusterInvoker

真正的調用又委托給了:FailoverClusterInvoker

從以上代碼注釋中可以看出,FailoverClusterInvoker,通過負載均衡器選擇"最優(yōu)"的Invoker發(fā)起遠程調用

這里選擇了:RegistryDirectory$DeleteInvoker其實就是一個InvokerWrapper

真正干活的是ListenerInvokerWrapper

繼續(xù)遞進:調用ProtocolFilterWrapper

最終來到了ProtocolFilterWrapper的匿名內部類:

把調用過程委托給了filter調用鏈路,至此,Invoker的使命完成了。相信更深的調用邏輯,通過分析Filter就能找到答案了

三? FailOverClusterInvoker選擇Invoker過程既FilterChain調用鏈的組裝

在第二節(jié)中,有分析服務發(fā)布調用過程,最紅是委托給了Filter調用。我們在分析的時候,有意的忽略掉了部分調用細節(jié),只是為了更好的梳理出整個調用鏈路。下面就分析一下在負載均衡器選擇Invoker的詳細邏輯

故事的開始當然是從FailoverClusterInvoker的invoke開始,FailoverClusterInvoker沒有自己實現invoke,其父類AbstractClusterInvoker實現了:

尋找Invoker的時候委托給了RegistryDirectory:

最終的Invoker尋找在RegistryDirectory里面維護的一個字段:methodInvokerMap里面查詢即可

查詢到全量的數據之后,就通過負載均衡器選擇,完成Invoker的選擇

那RegistryDirectory的methodInvokerMap又是在什么時候獲得調用方法和Invoker的對應關系的呢?

通過跟蹤字段的調用來源

最終確認: RegistryProtocol#doRefer時會調用到如上方法里面,生成method和Invokers的對應關系

以上,將服務發(fā)布,服務調用的過程做了較為粗略和完整的說明

四 結論證明

在前言部分有說過,先給出部分結論:

1 所有被標記了@service和使用標記的元素,均會被spring解析成ServiceBean

2 所有被標記了@Reference和使用的元素,均會被spring解析成ReferenceBean

這是怎么做到的呢?

在結合xml使用的時候,dubbo有引入DubboNamespaceHandler,該handler會解析相關的xml標簽,完成如上功能:

而在springboot應用中,dubbo有引入:ServiceAnnotationBeanPostProcessor

該類是一個前置處理器,會掃描@service標記的類,通過構建BeanDefinitionBuilder完成ServiceBean的注冊:

同樣的:springboot應用中引入了ReferenceAnnotationBeanPostProcessor

ReferenceAnnotationBeanPostProcessor是一個后置處理器,在Bean初始化時會被調用,注入相應的代理類

創(chuàng)作不易,如果對你有幫助,請點贊+收藏!

你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網查看詳情吧

文章名稱:朝花夕拾---dubbo源碼分析-創(chuàng)新互聯
分享網址:http://jinyejixie.com/article42/deoghc.html

成都網站建設公司_創(chuàng)新互聯,為您提供小程序開發(fā)電子商務、網頁設計公司App開發(fā)、網站排名、虛擬主機

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯

成都app開發(fā)公司
寿宁县| 渭南市| 游戏| 开鲁县| 德保县| 宾阳县| 德令哈市| 平果县| 屯昌县| 长岭县| 唐海县| 思南县| 大同市| 郑州市| 喀什市| 阿尔山市| 赤水市| 乐清市| 德兴市| 台江县| 察哈| 鄂尔多斯市| 女性| 巨鹿县| 辛集市| 阿尔山市| 溧水县| 龙南县| 乌拉特后旗| 正安县| 钟山县| 丽水市| 乌审旗| 年辖:市辖区| 宾阳县| 五大连池市| 涟源市| 抚顺市| 周至县| 济南市| 喀喇沁旗|