Hadoop RPC概述

Hadoop作爲一個存儲與服務的基礎性平臺,它的內部又採用了master/slave架構,那麼其內部通信和與客戶端的交互就是必不可少了。Hadoop在實現時拋棄了JDK自帶的一個RPC實現——RMI,而自己基於IPC模型實現了一個高效的輕量級RPC。


整體結構

    在IPC(inter process call,進程間的通信)包中,最重要的3個類是Server,Client和RPC,它們具有層次化的結構


  1. 1.RPC
  2.  (1) RPC類是對Server、Client的具體化。
  3.  在RPC類中規定,客戶程序發出請求調用時,參數類型必須是Invocation從服務器返回的值類型必須是ObjectWritable。
  4.  爲了加強理解,可以查看測試類TestIPC。在那裏,規定的參數類型與返回值類型都是LongWritable。
  5. (2) RPC類是對Server、Client的包裝,簡化用戶的使用。
  6.  如果一個類需充當服務器,只需通過RPC類的靜態方法getServer獲得Server實例,然後start。同時此類提供協議接口的實現。如果一個類充當客戶端,可以通過getProxy或者waitForProxy獲得一個實現了協議接口的proxy object,與服務器端交互。
  7.  爲了加強理解,可以查看測試類TestRPC,在那裏,實現的協議接口爲TestProtocol。
  • 2.Server類

  1.  (1).啓動Listener進程。
  2.  如果收到需要建立連接的請求,將建立連接,然後在上面捕獲讀操作的命令。收到命令之後,將把解析客戶端發過來信息的工作委派給Connection。Connection把信息封裝到Call對象中,放入隊列中,待Handler處理。
  3.  (2).啓動指定數目的Handler線程,處理客戶端對指定方法調用的請求,然後把結果返回給客戶端。
  •  3.Client類

  1.  用Call封裝好調用信息,然後藉助從連接池中取出的Connection向服務器端發送,等待結果。如果到指定服務器的Connection不存在,將馬上建立。Connection線程讀取服務器方法調用的返回信息。完成之後,通知主線程。

客戶端C要發起向服務端S的關於方法M調用,過程如下:
    1. C首先創建一個通向S的連接getConnection,然後將此次調用放入CallList裏,這樣客戶端就可以同時發生很多調用,每個調用用ID來識別。

    2. 發送調用參數

    調用參數是Client的調用方(比如NameNode,DataNode等)指定的,一般就是一個Invocation對象,裏面包含要調用的方法和參數。瞭解JAVA動態代理類java.lang.reflect.Proxy會對這裏的理解有很大幫助。

    3. 等待調用結果

    Client.Connection是個線程類,啓動了之後唯一做的時候就是等待調用結果


    對於服務器端,其有一個方法start指定了啓動服務器開始監聽,這個start被四個類調用,分別是TaskTracker.initialize,Namenode.initialize,Jobtracker.offerService,Datanode.startDatanode顯然,任何兩者之間的通信都是考這個client-server模型實現的。
    server start後,幹了三件事
    1. 啓動listen,監聽客戶端Call
    2. 啓動response,隨時準備將處理結果發回client
    3. 啓動10個handler,處理具體的請求。

    這裏必須對
java NIO機制瞭解,才能看的明白。這裏,可以參考博文:(todo)

當客戶端調用來到的時候
   1. listen首先將調用doaccept將Connection附加給selectionkey,然後調用doread添加,doread會調用Connecton的方法將調用添加到調用列表,該列表是BlockingQueue,其保持列表先進先出的特性而且支持同步
   2. listen將call添加到calllist後,handler因爲一直在檢測calllist,於是其立刻開始處理,處理完畢後,其將結果保存在call對象中,然後調用response開始向客戶端寫。這裏hadler調用的call只是一個未實現的方法,具體實現在RPC.Server中,這點需要注意。
   3. Response也監視responselist,如果responselist中某個call需要將結果寫入客戶端,就寫出,當某個call的結果被髮送完畢,從responselist中刪除該call對象。

    這裏有個細節:handler完成call之後就開始向客戶端寫call結果,但是結果可能太多,無法通過一次性發送完畢,而發送之後還要等待client接受完畢才能再發,如果現在handler在那裏等待客戶端接受完畢,然後再發,效率不高。解決辦法是handler處理完畢之後,只向client發送一次處理結果。如果這一次將處理結果發送完畢,接下來就沒有response的事情了,如果沒有發送完畢,接下來response負責將剩下的處理結果發送給客戶端。這樣handler的併發量會大一些。

    服務器實現中大量利用監視隊列,比如handler就直觀堅持calllist,一旦發現數據就開始處理,而response就監視responselist,發現數據需要發送就開始發送。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章