1. 程式人生 > >dubbo原理解析

dubbo原理解析

這是本人對於 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、