Dubbo源碼分析1

http://humn-chou.iteye.com/blog/1866272?utm_source=tuicool&utm_medium=referral


這是本人對於Dubbo源碼分析的系列一,沒有說明Dubbo是什麼,不清楚請先了解,此處只是爲了給自己做個筆記,也給正在學習Dubbo的同學一些借鑑,後期會繼續奉上所有關於Dubbo的邏輯分析,包括Dubbo簡介、初始化與請求細節、註冊中心、監控中心、治理中心等(由於Dubbo本身的文檔已經非常詳細了,這裏只是重構)。 

A. Dubbo初始化、請求處理過程:(此處不涉及非常細節處,均以dubbo協議爲例) 
一、 Dubbo提供者初始化過程分析: 
a) Dubbo解析xml,初始化且暴露所有服務 
b) 由服務配置類ServiceConfig進行初始化工作及服務暴露入口 
i. ServiceConfig.export(); 
c) 服務可以多協議暴露 
i. ServiceConfig.doExportUrls(); 
d) 在某個協議下暴露服務 
i. ServiceConfig.doExportUrlsFor1Protocol(); 
e) 將服務實現類轉化成invoker 
i. proxyFactory.getInvoker(service,interface,url); 
ii. 提供者端的invoker封裝了服務實現類、URL、Type,狀態均是隻讀,線程安全,是Dubbo中核心模型,Dubbo中的是實體域,其他所有模型都向它靠攏或轉化成它,是一個可執行體,通過發起invoke來具體調用服務類,它可能是個本地實現類,也可能是個遠程實現類,也可能是個集羣實現invoker,由ProxyFactory產生,具體是AbstractProxyInvoker 
f) 暴露封裝服務的Invoker 
i. Protocol.export(invoker); 
ii. Protocol是Dubbo中的服務域,只在服務啓用是加載且無狀態,天生線程安全,它是實體域Invoker暴露和引用的主功能入口,它負責Invoker的生命週期管理,是Dubbo中遠程服務調用層。Dubbo有多種協議支持,有dubbo、http、rmi、hessian、injvm、webService等,下面具體說明服務暴露的細節,包括服務的註冊、訂閱、暴露、過濾器、監聽器的初始化,其中服務的暴露則爲Dubbo中的一重點。 
g) 註冊中心協議集成,裝飾真正暴露引用服務的協議,增強註冊發佈功能 
i. RegistryProtocol.export(invoker); 
ii. ServiceConfig中的protocol是被多層裝飾的Protocol,是DubboProtocolRegistryProtocolProtocolListenerWrapperProtocolFilterWrapper(此處是以dubbo協議爲例,還有HttpPtotocol、HessianProtocol、RmiProtocol),其中ProtocolFilterWrapper是負責初始化invoker所有的Filter、ProtocolListenerWrapper是負責初始化暴露或引用服務的監聽器、RegistryProtocol是負責註冊服務到註冊中心與向註冊中心訂閱服務、DubboProtocol是負責服務的具體暴露與引用,且DubboProtocol也負責網絡傳輸層、信息交換層的初始化及底層NIO框架的初始化 
h) 註冊中心協議處理invoker後交給具體協議進行服務暴露 
i. RegistryProtocol.doLocalExport(invoker) 
ii. RegistryProtocol對原始invoker做一些簡單狀態後交給具體協議暴露,協議不關係invoker如何生成,由上層傳入。接下來就是協議對invoker的暴露,此步驟是Dubbo中的核心。 
i) 協議層暴露服務前初始化過濾器與服務暴露引用的監聽器 
i. 此步驟由上面提到的ProtocolListenerWrapper、ProtocolFilterWrapper完成,它們是協議的裝飾者,增強功能(裝飾模式大量使用在Dubbo中)。 
j) 協議暴露服務 
ii. DubboProtocol.export(); 
iii. 進入遠程調用層Protocol,此層封裝了所有remote層邏輯,對上層透明,暴露服務大致可以分爲兩步,第一是將invoker轉化成Exporter;第二是根據URL綁定IP與端口建立NIO框架的Server;此兩步的聯繫是通過URL關聯在一起,協議層緩存了所有暴露的服務,其中key是由group、serviceName、version、port組成,它們的組合具體一個暴露服務,當NIO客戶端發起遠程調用時,NIO服務端通過此key來決定具體調用執行哪個Exporter,即執行的Invoker,對於NIO框架的底層通信下面會有講解。 
j) 協議層創建Exporter後創建NIO Server完成服務的暴露 
i. DubboProtocol.openServer(url); 
ii. 創建封裝了Inoker,key的DubboExporter後,通過URL創建NIO Server,且緩存暴露的Exporter,防止重複暴露。另外,同一個JVM中相同協議的服務共享同一個Server,不同服務中只有accept、idleTimeout、threads、heartbeat參數的變化會引用Server中屬性的變化,但同JVM中同協議的服務均是引用同一個Server,第一個服務暴露是創建Server,其他服務的暴露是Server最多隻是重置個別參數。 
 

k) 協議層創建NIO Server,並緩存Server 
i. DubboProtocol.createServer(url); 
ii. Dubbo底層通信是通過支持異步、事件驅動的NIO網絡編程框架,如:Netty、Mina、Grizzly,此框架是典型的Reactor模式使用,使得單個線程處理多個請求,且支持多請求並行執行,NIO接受請求處理流程是讀取請求數據解碼執行業務邏輯編碼發送迴應消息,Dubbo是對NIO框架的再次抽象封裝,加入一些Dubbo需要的邏輯,通過抽象擴展Handler完成,如HeaderExchangerHandler完成請求-響應模式、同步轉異步模式消息發送,AllChannelHandler通過線程池完成請求、響應、連接等並行執行,下面會詳細介紹。 
iii. Exchangers.bind(url,requestHanler); 
iv. Exchangers是門面類,Exchanger的邏輯封裝在裏面,通過此FACADE調用Exchanger邏輯,Dubbo目前只有一個HeaderExanger實現。從協議層進入Exchanger標誌着程序進入了remote層,此層有消息交換層、網絡傳輸層。當協議層調用bind(url,requestHanler)方法並傳入最原始的處理Handler時,接下來就是remote層的Server和Hanlder及其他參數初始化的過程。 
v. HeaderExchanger.bind(url,requestHandler); 

vi. 此處是消息交換層與網絡傳輸層初始化的入口,且負責將初始化後的Server傳回給協議層。處理流程大致是Dubbo一系列Handler初始化、Server初始化。Handler包裝過程是 協議層傳入的原始requestHandlerHeaderExchangerHandlerDecodeHandlerAllChannelHandlerHeartbeatHandlerMultiMessageHandlerNettyServer[NettyHandler、NettyCodecAdapter]HeaderExchanerServer,HeaderExchanerServer封裝了最終的Server,返回給上層協議層,NettyHandler、NettyCodecAdapter是NIO框架的直接處理Handler,NIO框架接受到消息後,先由NettyCodecAdapter解碼,再由NettyHandler處理具體業務邏輯,再由NettyCodecAdapter編碼後發送,NettyServer是個很重要的類,它既是Server又是Handler,而HeaderExchangerServer只是Server,所有NettyServer參與的Handler的處理過程,MultiMessageHandler是多消息處理Handler、HeartbeatHandler是處理心跳事件的Handler、AllChannelHandler是消息派發器,負責將請求放入線程池,並行執行請求,且Dubbo有多種線程模型、DecodeHandler是編碼解碼Handler、HeaderExchangerHandler是信息交換Handler,將請求轉化成請求-響應模式與同步轉異步模式,地位非常重要、requestHandler最後執行的Handler,它會在協議層選擇Excporter後選擇Invoker,進而執行Filter與invoker,最終執行請求服務實現類方法。 
其中NIO框架的通信管道Channel也被Dubbo封裝了,Channel直接觸發事件並執行Handler,有ChannelNettyChannelHeaderExchangerChannel,通信管道Channel在有客戶端連接Server時觸發創建並封裝成NettyChannel,再由HeaderExchangerHandler創建HeaderExchangerChannel,負責請求-響應模式的處理,注意NettyChannel其實也是個Handler,而HeaderExchangerChannel只是個Channel,是Handler的類說明它也具體Handler特性。 
另外,還初始化一些參數,有AllChannelHandler的線程池模型、NettyServer的codesc解碼編碼方式,timeout超時時間,connectTimeout連接超時時時間,accepts提供者最大接受連接數設置,ildeTimeout時間設置,此處的參數得到都是爲了後期可能重置準備。還有消息的序列化與發序列化工作全在NettyCodecAdapter中發起完成。 
至此,分析了Dubbo初始化remote層所有初始化流程,還有,對於Transporters也是個門面類,內部調用網絡傳輸層的邏輯,如:NettyTransporter、MinaTransporter。 
附上連接過程:(當有客戶端連接Server時) 
0.NettyHandler.connected() 
1.NettyServer.connected() 
2.MultiMessageHandler.connected() 
3.HeartbeatHandler.connected() 
4.AllChannelHandler.connected() 
5.DecodeHandler.connected() 
6.HaderExchangeHandler.connected() 
7.requestHandler.connected() 
8.執行服務的onconnect事件的監聽方法 
下面是Handler、Server、Channel的結構圖: 



l) 將初始化後的Server返回協議層 
i. 創建好的Server返回,此Server對象很重,緩存 
m) 協議層將暴露後的Exporter返回給註冊中心協議層,最後返回給ServiceConfig進行緩存 
i. 協議層成功返回Exporter給註冊中心協議層,標誌着服務暴露完畢,接下來是與註冊中心的操作,邏輯上看,註冊中心負責服務的註冊與發現,所有提供者向註冊中心註冊服務,並訂閱重載配置,所有消費者向註冊中心註冊服務,並訂閱服務,消費者通過註冊中心自動發現所有服務提供者,且本地緩存提供者類表,註冊中心宕機也不影響消費者調用;程序上看,註冊中心也是普通的RPC服務,所有消費者、提供者與註冊中心都是長連接。Dubbo目前註冊中心服務有MulticastRegistry、ZookeeperRegistry等,關於註冊中心的詳細介紹待後期奉上。 
ii. RegistryProtocol.getRegistry(); 
iii. 得到具體註冊中心服務且連接註冊中心,此時提供者作爲消費者引用註冊中心核心服務RegistryService 
iv. Registry.register(url); 
v. 調用遠端註冊中心的register()方法進行服務註冊,且若有消費者訂閱此服務,則推送消息讓消費者引用此服務,註冊中心緩存了所有提供者註冊的服務以供消費者發現。 
vi. Registry.subscribe(url,listener); 
vii. 提供者向註冊中心訂閱所有註冊服務的覆蓋配置,當註冊中心有此服務的覆蓋配置註冊進來時,推送消息給提供者,讓它重新暴露服務,這由管理頁面完成。 
viii. 返回暴露後的Exporter給上層ServiceConfig進行緩存,便於後期撤銷暴露。 
ix. 總結:Exporter的創建、Server的創建、服務的註冊與訂閱,這些邏輯都是分離的,它們是通過URL聯繫在一起的。一般情況下,同JVM同協議下的服務共享同一個Server,且消費端的引用這些服務的也可共享一個Client,從而實現多個服務共享同一個通道進行通信,且是基於長連接下,減少了通信的握手次數,高效率通信,另外,遠程調用層與信息交換層及網絡傳輸層是Dubbo的核心。 
二、 Dubbo消費者初始化過程分析: 
a) Dubbo解析xml,初始化所有注入的引用服務及init=true引用服務 
b) 所有dubbo引用服務均由ReferenceConfig入口進行服務的引用 
i. ReferenceConfig.get(); ReferenceConfig.init(); 
ii. 消費者最終的得到的是服務的代理,在創建代理前初始化所有配置信息,此過程是線程安全的。引用服務的大致過程是由遠程調用創建消費者端Invoker,再由ReferenceConfig創建代理返回,此過程的核心是創建消費端的Invoker。在引用服務前,ReferenceConfig先需要判斷是否是引用本地服務injvm、是否是點對點直連、是否是通過註冊中心連接,判斷之後進行最重要的一步:服務的引用。 
c) 進入遠程調用層進行服務的引用 
i. Protocol.refer(interface,url); 
ii. 此方法返回的是個集羣invoker,若有多個提供者提供服務,Dubbo將多個服務Invoker僞裝成一個集羣Invoker,且這個集羣Invoker內部的多個invoker,由Directory完成,Directory與List類似,但由不同,當提供者推送消息過來後,Directory可以動態變化,還可以通過Router路由提供者及LoadBalance根據負載均衡算法選中一個提供者,所以當上層進行Invoker調用時,會是:Cluster.invoke()Directory.list()Router.route()LoadBalance.select()invoke.invoke();另外,在invoker轉成proxy時,Dubbo對代理也有裝飾,如Stub,這個可以實現在真正調用invoker代理前可以做一些事情,類似AOP功能。上面是大致說明以下消費者引用服務的過程,下面詳細說明。 
d) 首先進入註冊中心遠程調用層RegistryProtocol,且它也經過了ProtocolFilterWrapper、ProtocolListenerWrapper裝飾,功能增強 
i. RegistryProtocol.refer(); 
ii. 同提供者相同,消費者也首先需要連接註冊中心,即引用註冊中心這個特殊的RPC服務,並通過註冊中心進行服務的訂閱與註冊。然後判斷引用是否是註冊中心RegistryService服務,若是繞過註冊中心與集羣等直接返回剛得到註冊中心服務即可,若不是,則說明是普通服務,則需要進入註冊中心與集羣下面的邏輯。在選擇集羣策略前,先需要判斷引用服務是否需要合併不同實現的返回結果,及是否配置group="*" merger="true" (配置詳細說明再說),若配置了,則選擇默認的分組聚合集羣策略,若沒配置,則選擇配置的集羣策略cluster="failback"或默認策略。下面進入服務引用的重點邏輯分析。 
e) 服務引用,且向上層返回 
i. RegistryProtocol.doRefer(cluster,registry,type,url); 
ii. 消費端引用服務主要邏輯部分,服務引用大致邏輯是組合url、type創建目錄類Directory,此類非常重要,它的功能很複雜,可以看成是NotifyListener服務通知監聽器、可以看成Protocol、Registry的聚合類、可以看成一個消費端的List,但它又不同於List,他可以隨着註冊中心的消息推送而動態變化服務的Invoker數,時刻監聽着提供者的變化,典型觀察者模式的使用,它封裝了所有服務真正引用邏輯、覆蓋配置、路由規則等邏輯,初始化時只需要向註冊中心發起訂閱請求,其他邏輯均是異步的處理,包括服務引用等,且對上層Cluster層是透明的,ResitryProtocol將多個Invoker僞裝成一個Invoker返回給上層來轉化成代理,上層甚至不知道這是個集羣Invoker,在僞裝成一個Invoker時,Cluster也被裝飾了,增強了Mock功能,這個詳細暫不在此處說明。頂層得到僞裝後的Invoker,當調用時,會根據初始化時的集羣策略、負載均衡策略、路由策略進行選擇調用某個Invoker。下面看看Directory的初始化與服務異步引用的分析及集羣的處理步驟。 
f) 目錄類Directory初始化、服務訂閱、集羣僞裝 
i. 在RegistryProtocol中會根據url、type、protocol、registry初始化Directory,Directory功能非常強大,此處暫不說明詳細功能。訂閱服務前,註冊中心首先註冊服務,便於後期的監控中心提取數據,通過Directory訂閱服務directory.subscribe(url),當有服務提供時,註冊中心會推送服務消息給消費者,消費者再進行服務的引用,此處暫不詳細說明註冊中心的處理邏輯。下面是Directory中的代碼塊 
,接下來服務的引用與變更全部由Directory異步完成,集羣策略會將Directory僞裝成一個invoker, cluster.join(directory),此代碼就是僞裝邏輯,Dubbo有很多集羣策略,可以配置切換,具體集羣邏輯暫不屬於這裏,後期說明。RegistryProtocol再將僞裝後的Invoker返回給上層ReferenceConfig用來創建代理,所以消費者端的對象引用的遠程服務其實引用的都是個代理,真正邏輯只有在調用時觸發,包括Stub、Proxy、Mock、Cluster、Router、LoadBalance、Filter、Invoker、NIO框架底層通信。 
g) Directory服務引用、NIO框架初始化 
i. 註冊中心接收到消費端發送的訂閱請求後,會根據提供者註冊服務的列表,推送服務消息給消費者,此處的邏輯不同的註冊中心實現邏輯不通,詳細暫不說明,消費者端接受到註冊中心發來的提供者列表後,進行服務的引用,觸發Directory監聽器的可以是訂閱請求、覆蓋策略消息、路由策略消息(後兩者由管理頁面設置),接下面就是服務的引用過程,這邏輯都隱藏在Directory中。 
invoker = new InvokerDelegete<T>(protocol.refer(serviceType, url), url, providerUrl); 
h) 真正進入遠程調用層,進行服務的引用與NIO框架的初始化 
i. DubboProtocol.refer(type,url); 
ii. 同服務的暴露邏輯相同,服務的引用步驟也分爲兩步,一是消費端Invoker的創建,如DubboInvoker,而是NIO框架的Client創建,這兩步驟雖然是也是分離的,但它們不是通過URL聯繫在一起的,而是Invoker聚合了Client,當調用Invoker時,底層實際上是調用Client邏輯進行底層通信。 
iii. new DubboInvoker<T>(serviceType, url, getClients(url), invokers); 
iv. Invoker創建,可以看出Invoker聚合了Client,此Invoker對象很重,遠程調用層進行了緩存invokers.add(invoker);。 
v. getClients(url) 
vi. 此代碼負責NIO框架Client創建及初始化,和提供者初始化相似,消費者的初始化也基本上圍繞着Client、Handler、Channel對象的創建與不斷裝飾的過程,不同的是消費者底層是與提供者Server建立連接,此過程在remote層下完成,remote層可分爲消息交換層與網路傳輸層即Exchanger與Transporter層,還有,我們在說提供者初始化時,說過同個JVM中相同協議的服務共享一個Server,同樣在消費者初始化時,引用同一個提供者的所有服務可以共享一個Client進行通信,這也就實現了Server-Client在同一個通道中進行通信,實現長連接的高效通信,但是在服務請求數據量比較大時或請求數比較多時,可以設置每服務每連接或每服務多連接可以提高通信效率,具體是通過消費者方connections=2設置連接數。所有消費者端Client有兩種,一種是共享型Client,一種是創建型Client,當然共享型Client屬於創建型Client一部分,下面具體說說這兩種Client創建的細節,也是服務引用的重要細節。 
 

vii. getSharedClient(url) 
viii. 此爲創建共享型Client,共享型Client是指消費者引用同一提供者的服務時,使用同一個Client來提高通信效率,所以對於消費者來說,它連接的每個提供者都需要創建一個創建型Client,其他來自相同提供者的服務引用即可共享此Client,關於創建型Client的創建下面再說。對於共享型Client雖然可以提高通信效率,但會帶來一個問題,就是如果所有共享一個Client的服務中的某個服務close了Client會導致其他服務都不能繼續通信,這是個安全性問題,Dubbo的解決方案是通過計數的方式來控制這個安全問題,並在共享Client真正關閉後創建一個懶加載的幽靈Client,以備特殊情況使用(此處不說非常細節)。 
 

ix. initClient(url) 
x. 此爲創建創建型Client,也是消費者端服務引用最核心的地方,封裝了服務引用中remote層初始化的所有邏輯,與提供者端類似,就是Client、Handler、Channel的創建與不斷裝飾的過程,在說Client創建細節前,先說說Client類型,與其他產品一樣,Dubbo中也有懶加載的概念,即Client分爲正常馬上連接的Client與懶加載的Client,懶加載的Client是個Client代理,當消費者真正調用服務時,纔會去初始化Client、Handler、Channel,也就是纔會與Server建立連接。 
xi. Client、Handler、Channel初始化 
xii. 此步驟是服務引用的核心的核心,邏輯完全封裝在Protocol遠程調用層,對於上層是完全透明的。在進行創建前,Dubbo默認開啓remote層的心跳機制與禁止BIO通信,心跳機制是提供者與消費者之間的心跳通信,主要是防止通信異常,如提供者宕機,消費者自動重連提供者。下面重點是服務引用即Client的創建,此過程完成由Directory發起,有關於Directory的細節,後期會專欄介紹此類。同提供者類似,服務引用無非也就是初始化信息交換層與網絡傳輸層即Exchanger與Transporter,且分別由門面類Exchangers與Transporters發起,Transporter返回的Client再經過Exchanger封裝裝飾後完成初始化並返回給上層Protocol。 


詳細是:遠程調用層Protocol傳入原始Handler,後續將是此Handler不斷裝飾的過程,下面是Handler與Server初始化過程:requestHandlerHeaderExchangerHandlerDecodeHandlerAllChannelHandlerHeartbeatHandlerMultiMessageHandlerNettyClient[NettyHandler、NettyCodecAdapter]HeaderExchanerClient 此處remote最終返回包裝了NettyClient的HeaderExchangerClient到Protocol層,與提供者相比,消費者有以下異同: 
1. 初始化的大致邏輯相同 
2. 提供者暴露服務是綁定IP,而消費者是與提供者建立連接 
3. 與NettyServer相同,NettyClient也是個Handler 
4. 與HeaderExchangerServer不同,HeaderExchangerClient也是個Channel,這點一定注意 
其中各個Handler、Client與提供者那裏基本類似,這裏不重複說明它們的功能,對於底層無非就是NIO框架的初始化,與Server建立連接。前面也說過了,返回到protocol層的Client被封裝成消費端的Invoker,再返回給重要的Directory,那裏動態引用了該服務所有與提供者建立後的Invoker,而真正protocol返回給上層的Invoker是封轉了Directory的集羣僞裝Invoker,當真正調用時,纔會根據集羣策略、路由策略、負載均衡策略從Directory選擇一個Invoker進行調用即Client與Server進行通信,所以Directory在Dubbo佔有非常重要的位置,它的功能很複雜。 
下面再說說消費者發起的Channel的創建: 
消費者的NIO框架初始化是有一步很重要,就是與提供者建立連接即Channel的創建,NIO框架採用的雙向通訊的通道Channel,而Dubbo對Channel也做了封裝,封裝過程是ChannelNettyChannelHeaderExchangerChannel,還有一點非常重要,查看Dubbo源碼可知,NettyChannel其實也是個Handler,而HeaderExchangerChannel只是個Channel。在消費者端發起連接時,提供者端與消費者端的NettyHandler將被觸發,將執行一系列的Handler或Server邏輯,在NettyHandler觸發連接時,執行channelConnected創建Channel,Dubbo對NIO的Channel進行了包裝,實現創建NettyChannel,它封裝了NIO的Channel與包裝Handler的NettyClient,值得注意的所有的事件都由NIO的Channel觸發,如:寫事件、讀事件、連接事件、斷開連接事件、出現異常事件。在Handler執行到HeaderExchangerHandler時,創建HeaderExchangerChannel,並且封裝從Handler創建並傳下來的NettyChannel。其中HeaderExchangerClient構造中有下面這段代碼: 

HeaderExchangerClient也有個封裝了NettyClient的HeaderExchangerChannel,注意這個,因爲這是消費者發起請求是底層通信的入口。 
下面給出Client與Channel結構圖,Handler圖上面已有: 


總結:所有的初始化,都是爲了消費者與提供者之間的通信做準備,下面請結合初始化過程,重點查看通信的過程。再說說,這裏的服務引用過程全部隱藏在Directory中,對上層完全透明,只有註冊中心觸發Directory進而觸發服務引用或變更,而上層來說,它接受到的是集羣僞裝後的Invoker,然後再將Invoker轉成Proxy,所以Spring中引用的是一個代理,只有消費者發起調用時,纔有一系列的集羣、路由、負載均衡邏輯,主要調用邏輯請看下面。 
補充:和提供者暴露服務有暴露監聽器一樣ExporterListener,消費者端有引用服務的監聽器InvokerListener,在服務引用時執行。 
三、 Dubbo消費者--提供者請求過程與響應過程: 
a) 大致過程 
i. 消費者發送請求提供者處理消費者接受請求 
ii. 在提供者與消費者端都初始化完畢時,提供者對外暴露的是Expoter、消費者對外提供的是Proxy,接下來就是從Proxy的執行到Exporter執行的過程,其中Dubbo中的會話域Invocation承載着提供者與消費者端的消息傳遞,並在每個線程棧中使用。下面是大致處理邏輯: 
----------------------------------1.消費者發起請求------------------------------------------- 
1. testService.hello();//消費者端呈現層引用的遠程服務,這其實就是個代理 
2. testServiceSub.hello();//proxy代理被Sub包裝了,增強Sub功能,類似AOP 
3. testServiceProxy.hello();//消費者端Invoker代理 
4. InvokerInvocationHandler.invoker();//由代理類執行的invocationHandler 
5. MockClusterInvoker.invoke();//集羣對集羣Invoker進行的包裝,Mock功能 
6. ClusterInvoker.invoke();//執行集羣僞裝的Invoker 
7. Directory.list();//查找僞裝在集羣后面的所有Invoker 
8. Router.route();//通過路由規則策略從list中選擇一些Invoker 
9. LoadBalance.select();//通過負載均衡選策略選中一個Invoker執行 
10. Filter.invoke();//執行所有消費者端Filter 
11. Invoker.invoke();//執行消費者端的Invoker即DubboInvoker 
12. HeaderExchangerClient.request();//信息交換Client執行請求,其中封裝了NettyClient、HeaderExchangerChannel 
13. HeaderExchangerChannel.request();//此類封裝了NettyClient,信息交換通道創建Request執行請求,並創建DefaultFuture返回 
14. NettyClient父類AbstractClient.send();//消費者端Client執行請求 
15. NettyChannel.send();//Netty通道執行請求發送 
16. Channel.write();//NIO框架通知執行寫操作,並觸發Handler 
17. NettyHanlder.writeRequested();//執行NIO框架的頂級Handler 
18. NettyCodecAdapter.encode();//執行NIO框架的編碼邏輯,以下執行Handler 
19. NettyClient父類AbstractPeer.send();//執行裝飾了Handler的NettyCient 
20. MultiMessageHandler.send();//多消息處理Handler 
21. HeartbeatHandler.send();//心跳處理Handler 
22. AllChannelHandler.send();//消息派發器Handler 
23. DecodeHandler.send();//編碼Handler 
24. HeaderExchangerHandler.send();//信息交換Handler 
25. requestHandler父類ChannelHandlerAdapter.send();//最後執行Handler,以上Handler的執行在消費者端是沒有意義,因爲Channel.write ()執行時,提供者端已經收到消息了,也正在處理了,詳細邏輯後面再說,這裏爲了完整性才這樣寫(以上是消費者請求大致過程,下面是提供者接受請求後處理並響應消費者過程)。 
------------------------------2.提供者處理並響應請求-------------------------------------- 
26. NettyCodecAdapter.messageReceived();//提供者通過NIO框架通信並接受到消費者發送的信息,當然,這裏屏蔽了所有NIO框架的邏輯,也屏蔽了所有編碼解碼與序列化反序列化的邏輯 
27. NettyHandler.messageReceived();//提供者端的NIO頂級Handler處理 
28. NettyServer.received();//NIO框架的Server接受請求信息 
29. MultiMessageHandler.received ();//多消息處理Handler 
30. HeartbeatHandler.received ();//心跳處理Handler 
31. AllChannelHandler.received ();//消息派發器Handler 
32. DecodeHandler.received ();//編碼Handler 
33. HeaderExchangerHandler.received ();//信息交換Handler,請求-響應模式 
34. requestHandler.reply();//執行與Exporter交接的最初Handler 
35. getInvoker();//先得到提供者端的Exporter再得到相應的提供者端Invoker 
36. Filter.invoke();//執行所有提供者端的Filter,所有附加邏輯均由此完成 
37. AbstractInvoker.invoke();//執行封裝了服務實現類的原始Invoker 
38. testServiceImple.hello();//執行服務實現類邏輯 
39. NettyChannel.send();//HeaderExchangerHandler得到執行結果Response再返回給消費者,此代碼由HeaderExchangerHandler發起 
40. Channel.write ();//NIO框架通知執行寫操作,並觸發Handler 
41. NettyHanlder.writeRequested();//執行NIO框架的頂級Handler 
42. NettyCodecAdapter.encode();//執行NIO框架的編碼邏輯,以下執行Handler 
43. NettyServer父類AbstractPeer.send();//執行裝飾了Handler的NettyServer 
44. MultiMessageHandler.send();//多消息處理Handler 
45. HeartbeatHandler.send();//心跳處理Handler 
46. AllChannelHandler.send();//消息派發器Handler 
47. DecodeHandler.send();//編碼Handler 
48. HeaderExchangerHandler.send();//信息交換Handler 
49. requestHandler父類ChannelHandlerAdapter.send();//最後執行Handler,以上Handler的執行在提供者端也是是沒有意義,因爲Channel.write ()執行時,消費者端已經收到響應消息了,也正在處理了,詳細邏輯後面再說,這裏爲了完整性才這樣寫(以上是消費者請求與提供者接受請求並響應大致過程,下面是消費者接受到提供者響應後處理過程)。 
----------------------------------3.消費者接受響應------------------------------------------ 
50. NettyCodecAdapter.messageReceived();//提供者通過NIO框架通信並接受提供者發送過來的響應 
51. NettyHandler.messageReceived();//消費者端的NIO頂級Handler處理 
52. NettyClient.received();//NIO框架的Client接受響應信息 
53. MultiMessageHandler.received ();//多消息處理Handler 
54. HeartbeatHandler.received ();//心跳處理Handler 
55. AllChannelHandler.received ();//消息派發器Handler 
56. DecodeHandler.received ();//編碼Handler 
57. HeaderExchangerHandler.received ();//信息交換Handler,請求-響應模式 
58. DefaultFuture.received();//設置response到消費者請求的Future中,以供消費者通過DefaultFuture.get()取得提供者的響應,此爲同步轉異步重要一步,且請求超時也由DefaultFuture控制。 
-----------------------------------4.阻塞或異步斷點--------------------------------------- 
59. Filter.invoke();//消費者異步得到響應後,DubboInvoker繼續執行,從而Filter繼續執行,從而返回結果給消費者。 
60. InvokerInvocationHandler.invoker();//執行invocationHandler後續代碼 
61. testServiceProxy.hello();//消費者端Invoker代理後續代碼 
62. testServiceSub.hello();//執行後續代碼 
63. testService.hello();//執行後續代碼 
64. 呈現結果給消費者客戶端 
總結:消費者端的DubboInvoker發起請求後,後續的邏輯可以說是異步的或是指定超時時間內阻塞的,直到得到響應結果後,繼續執行DubboInvoker中邏輯。對於異步請求時,消費者得到Future,其餘邏輯均是異步的。以上主要核心邏輯,對於附加功能,大部分由Filter增強完成。消費者還可以通過設置async、sent、return來調整處理邏輯,async指異步還是同步請求,sent指是否等待請求消息發出即阻塞等待是否成功發出請求、return指是否忽略返回值即但方向通信,一般異步時使用以減少Future對象的創建和管理成本。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章