HDFS分析(二)
HDFS中簡(jiǎn)單的分為:Client,DataNode,NameNode三大類,其中他們之間的通訊一共有這么幾種:
Client <=====>NameNode;Client <=====>DataNode;NameNode <======>DataNode;DataNode<=====>DataNode幾種,其中涉及到很多網(wǎng)絡(luò)通訊的封裝,也涉及到Hadoop的IPC機(jī)制。
? ?他們的通訊如下:
?
? ?主要類的類圖:
?
?HDFS的通訊方面的代碼寫的不是很優(yōu)雅,相互依賴太多,只有一點(diǎn)點(diǎn)進(jìn)行分析
?
總體
DFSClient與NameNode的通訊使用了Hadoop自身的ipc通訊機(jī)制,ipc機(jī)制使用了Hadoop自身的IO和序列化方式,沒有使用JDK自身的序列化方式
是因?yàn)镴DK自身的序列化方式過(guò)于重量效率不高
?
NameNode和Datanode都是最頂層的接口VersionedProtocol,實(shí)現(xiàn)了該接口就表示這個(gè)類將使用Hadoop的RPC機(jī)制
?
Hadoop RPC結(jié)構(gòu)分為Server,Client,以及協(xié)議接口和實(shí)現(xiàn)
?
RPC是對(duì)外的接口,主要提供了getServer()和getProxy()方法,getServer()為指定協(xié)議創(chuàng)建服務(wù)器端的實(shí)例,在指定的地址和端口上啟動(dòng)服務(wù)
getProxy()創(chuàng)建了一個(gè)指定協(xié)議的服務(wù)器端實(shí)例的代理
?
Server端:
ipc.Server類代碼比較復(fù)雜,內(nèi)部類比較多,Server處理網(wǎng)絡(luò)方面使用了NIO Reactor模式
ipc.Server.Listener:服務(wù)器端的監(jiān)聽類,監(jiān)聽來(lái)自客戶端的連接請(qǐng)求,以及為ipc.Server.Listener.Reader注冊(cè)讀事件,創(chuàng)建ipc.Server.Connection實(shí)例
ipc.Server.Listener.Reader:ipc.Server.Listener為Reader注冊(cè)了讀事件,Reader讀取客戶端過(guò)來(lái)的數(shù)據(jù),當(dāng)讀滿一個(gè)RPC的請(qǐng)求數(shù)據(jù)的時(shí)候處理這些數(shù)據(jù)生成一個(gè)ipc.Server.Call實(shí)例,這個(gè)實(shí)例放入server的BlockingQueue中。
ipc.Server.Handler:一直監(jiān)聽著server的BlockingQueue,如果Reader把Call實(shí)例加入的話,Handler從隊(duì)列里面取出,使用JDK的反射執(zhí)行相關(guān)的方法,
執(zhí)行完后交有Responder設(shè)置Call的response,然后寫回給客戶端,Responder同步的寫回客戶端的一個(gè)Call的response,其他的Call的結(jié)果將有Responder異步寫回
基本的類圖和流程如下:
?
?
Client端:
先看相關(guān)的類圖:
Client:客戶端的實(shí)現(xiàn)類
Client.ConnectionId:到RPC服務(wù)端對(duì)象連接的標(biāo)識(shí)
Client.Connection:到RPC服務(wù)端的連接,由Client.ConnectionId進(jìn)行唯一標(biāo)識(shí),放在Client的鏈接池里面
Client.Call:存儲(chǔ)客戶端的調(diào)用參數(shù),以及服務(wù)器端后續(xù)返回的參數(shù)
RPC.Invoker:對(duì)InvocationHandler的實(shí)現(xiàn),提供invoke方法,截獲RPC客戶端對(duì)RPC服務(wù)端對(duì)象的調(diào)用
客戶端調(diào)用的大致流程是:
1.RPC類的getProxy()最終是調(diào)用JDK動(dòng)態(tài)代理的方法創(chuàng)建一個(gè)VersionedProtocol或者其子接口的代理類,在此創(chuàng)建了InvocationHandler的實(shí)現(xiàn)RPC.Invoker的實(shí)例
2.在Invoker構(gòu)造方法中創(chuàng)建Client.ConnectionId,以及根據(jù)SocketFactory獲得對(duì)應(yīng)的Client實(shí)例
3.當(dāng)客戶端調(diào)用一個(gè)服務(wù)器端的方法時(shí),Invoker的invoke方法被調(diào)用,invoke方法執(zhí)行client的call方法
4.Client的call方法中創(chuàng)建了Client.Call實(shí)例,獲得Client.Connection實(shí)例(從連接池中獲得或者新建一個(gè),當(dāng)是新建的一個(gè)Connection時(shí),先和服務(wù)器端進(jìn)行連接,
然后寫入rpcHeader和ConnectionHeader,從連接池中獲得的是不需要設(shè)置的),其他還有如Connection的回收這里不表
5.在第4步之后,在connection中寫入實(shí)際要調(diào)用的數(shù)據(jù)
6.Connection是個(gè)線程,在run方法中是同步等待服務(wù)器端的返回
7.call實(shí)例設(shè)置value,返回給調(diào)用者
?
最后給個(gè)client和server之間調(diào)用示意圖:
轉(zhuǎn)載于:https://www.cnblogs.com/nod0620/archive/2012/03/27/2417760.html
與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖總結(jié)
- 上一篇: RabbitMQ introductio
- 下一篇: 吃饱了,就来写点东西吧。讲一个真实的故事