如何更好地學習dubbo源代碼(轉)

很榮幸,做爲這樣一款業界使用率和好評率出衆的RPC框架的維護者,今天這個文章主要是想幫助那些熱愛開源的同窗,更好的來研究dubbo的源代碼。spring

 1、Dubbo總體架構數據庫

一、Dubbo與Spring的整合 Dubbo在使用上能夠作到很是簡單,不論是Provider仍是Consumer均可以經過Spring的配置文件進行配置,配置完以後,就能夠像使用 spring bean同樣進行服務暴露和調用了,徹底看不到dubbo api的存在。這是由於dubbo使用了spring提供的可擴展Schema自定義配置支持。在spring配置文件中,能夠像、這樣進行配置。 META-INF下的spring.handlers文件中指定了dubbo的xml解析類:DubboNamespaceHandler。像前面的被解 析成ServiceConfig,被解析成ReferenceConfig等等。 二、jdk spi擴展 因爲Dubbo是開源框架,必需要提供不少的可擴展點。Dubbo是經過擴展jdk spi機制來實現可擴展的。具體來講,就是在META-INF目錄下,放置文件名爲接口全稱,文件中爲key、value鍵值對,value爲具體實現類 的全類名,key爲標誌值。因爲dubbo使用了url總線的設計,即不少參數經過URL對象來傳遞,在實際中,具體要用到哪一個值,能夠經過url中的參 數值來指定。 Dubbo對spi的擴展是經過ExtensionLoader來實現的,查看ExtensionLoader的源碼,能夠看到Dubbo對jdk spi作了三個方面的擴展:設計模式

(1)jdk spi僅僅經過接口類名獲取全部實現,而ExtensionLoader則經過接口類名和key值獲取一個實現;api

(2)Adaptive實現,就是生成一個代理類,這樣就能夠根據實際調用時的一些參數動態決定要調用的類了。緩存

(3)自動包裝實現,這種實現的類通常是自動激活的,經常使用於包裝類,好比Protocol的兩個實現類:ProtocolFilterWrapper、ProtocolListenerWrapper。 三、url總線設計 Dubbo爲了使得各層解耦,採用了url總線的設計。咱們一般的設計會把層與層之間的交互參數作成Model,這樣層與層之間溝通成本比較大,擴展起來也比較麻煩。所以,Dubbo把各層之間的通訊都採用url的形式。好比,註冊中心啓動時,參數的url爲: registry://0.0.0.0:9090?codec=registry&transporter=netty 這就表示當前是註冊中心,綁定到全部ip,端口是9090,解析器類型是registry,使用的底層網絡通訊框架是netty。網絡

 2、Dubbo啓動過程架構

Dubbo分爲註冊中心、服務提供者(provider)、服務消費者(consumer)三個部分。 一、註冊中心啓動過程 註冊中心的啓動過程,主要看兩個類:RegistrySynchronizer、RegistryReceiver,兩個類的初始化方法都是start。 RegistrySynchronizer的start方法:app

(1)把全部配置信息load到內存;負載均衡

(2)把當前註冊中心信息保存到數據庫;框架

(3)啓動5個定時器。 5個定時器的功能是: (1)AutoRedirectTask,自動重定向定時器。默認1小時運行1次。若是當前註冊中心的鏈接數高於平均值的1.2倍,則將多出來的鏈接數重定向到其餘註冊中心上,以達到註冊中心集羣的鏈接數均衡。 (2)DirtyCheckTask,髒數據檢查定時器。做用是:分別檢查緩存provider、數據庫provider、緩存consumer、數據庫 consumer的數據,清除髒數據;清理不存活的provider和consumer數據;對於緩存中的存在的provider或consumer而數 據庫不存在,從新註冊和訂閱。 (3)ChangedClearTask,changes變動表的定時清理任務。做用是讀取changes表,清除過時數據。 (4)AlivedCheckTask,註冊中心存活狀態定時檢查,會定時更新registries表的expire字段,用以判斷註冊中心的存活狀態。若是有新的註冊中心,發送同步消息,將當前全部註冊中心的地址通知到全部客戶端。 (5)ChangedCheckTask,變動檢查定時器。檢查changes表的變動,檢查類型包括:參數覆蓋變動、路由變動、服務消費者變動、權重變動、負載均衡變動。 RegistryReceiver的start方法:啓動註冊中心服務。默認使用netty框架,綁定本機的9090端口。最後啓動服務的過程是在NettyServer來完成的。接收消息時,拋開dubbo協議的解碼器,調用類的順序是

NettyHandler-》NettyServer-》MultiMessageHandler-》HeartbeatHandler-》AllDispatcher-》DecodeHandler-》HeaderExchangeHandler-》RegistryReceiver-》RegistryValidator-》RegistryFailover-》RegistryExecutor

二、provider啓動過程 provider的啓動過程是從ServiceConfig的export方法開始進行的,具體步驟是: (1)進行本地jvm的暴露,不開聽任何端口,以提供injvm這種形式的調用,這種調用只是本地調用,不涉及進程間通訊。 (2)調用RegistryProtocol的export。 (3)調用DubboProtocol的export,默認開啓20880端口,用以提供接收consumer的遠程調用服務。 (4)經過新建RemoteRegistry來創建與註冊中心的鏈接。 (5)將服務地址註冊到註冊中心。 (6)去註冊中心訂閱本身的服務。 三、consumer啓動過程 consumer的啓動過程是經過ReferenceConfig的get方法進行的,具體步驟是: (1)經過新建RemoteRegistry來創建與註冊中心的鏈接。 (2)新建RegistryDirectory並向註冊中心訂閱服務,RegistryDirectory用以維護註冊中心獲取的服務相關信息。 (3)建立代理類,發起consumer遠程調用時,實際調用的是InvokerInvocationHandler。

3、實際調用過程 consumer端發起調用時,實際調用通過的類是: 一、consumer:

InvokerInvocationHandler-》MockClusterInvoker(若是配置了Mock,則直接調用本地Mock類)-》FailoverClusterInvoker(負載均衡,容錯機制,默認在發生錯誤的狀況下,進行兩次重試)-》RegistryDirectory$InvokerDelegete-》ConsumerContextFilter-》FutureFilter->DubboInvoker

二、provider:

NettyServer-》MultiMessageHandler-》HeartbeatHandler-》AllDispatcher-》DecodeHandler-》HeaderExchangeHandler-》DubboProtocol.requestHandler-》EchoFilter-》ClassLoaderFilter-》GenericFilter-》ContextFilter-》ExceptionFilter-》TimeoutFilter-》MonitorFilter-》TraceFilter-》實際service

4、Dubbo使用的設計模式 一、工廠模式 ServiceConfig中有個字段,代碼是這樣的:

privatestaticfinalProtocolprotocol=ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();

Dubbo裏有不少這種代碼。這也是一種工廠模式,只是實現類的獲取採用了jdk spi的機制。這麼實現的優勢是可擴展性強,想要擴展實現,只須要在classpath下增長個文件就能夠了,代碼零侵入。另外,像上面的 Adaptive實現,能夠作到調用時動態決定調用哪一個實現,可是因爲這種實現採用了動態代理,會形成代碼調試比較麻煩,須要分析出實際調用的實現類。 二、裝飾器模式 Dubbo在啓動和調用階段都大量使用了裝飾器模式。以Provider提供的調用鏈爲例,具體的調用鏈代碼是在 ProtocolFilterWrapper的buildInvokerChain完成的,具體是將註解中含有group=provider的 Filter實現,按照order排序,最後的調用順序是

EchoFilter-》ClassLoaderFilter-》GenericFilter-》ContextFilter-》ExceptionFilter-》TimeoutFilter-》MonitorFilter-》TraceFilter

更確切地說,這裏是裝飾器和責任鏈模式的混合使用。例如,EchoFilter的做用是判斷是不是回聲測試請求,是的話直接返回內容,這是一種責任 鏈的體現。而像ClassLoaderFilter則只是在主功能上添加了功能,更改當前線程的ClassLoader,這是典型的裝飾器模式。 三、觀察者模式 Dubbo的provider啓動時,須要與註冊中心交互,先註冊本身的服務,再訂閱本身的服務,訂閱時,採用了觀察者模式,開啓一個listener。 註冊中心會每5秒定時檢查是否有服務更新,若是有更新,向該服務的提供者發送一個notify消息,provider接受到notify消息後,即運行 NotifyListener的notify方法,執行監聽器方法。 四、動態代理模式 Dubbo擴展jdk spi的類ExtensionLoader的Adaptive實現是典型的動態代理實現。Dubbo須要靈活地控制實現類,即在調用階段動態地根據參數決 定調用哪一個實現類,因此採用先生成代理類的方法,可以作到靈活的調用。生成代理類的代碼是ExtensionLoader的 createAdaptiveExtensionClassCode方法。代理類的主要邏輯是,獲取URL參數中指定參數的值做爲獲取實現類的key。

相關文章
相關標籤/搜索