Hadoop 中 IPC 的源碼分析

最近開始看 Hadoop 的一些源碼,展開 hadoop 的源碼包,各個組件分得比較清楚,因而開始看一下 IPC 的一些源碼。(版本是 1.0.4 中的 ipc 包,多謝 @上古進程 提醒)java

IPC模塊,也就是 進程間通訊模塊,若是是在不一樣的機器上,那就能夠理解爲 RPC 了,也就是遠程調用。事實上, hadoop 中的 IPC 也就是基於 RPC 實現的。安全

使用 sloccount 統計一下 ipc 包中代碼的行數,一共是 2884 行。也就是說,IPC 做爲hadoop的基礎組件,僅僅用了不到3000行的代碼,就完成得穩定且富有效率。網絡

IPC 中的關鍵類關係:

Hadoop IPC 主要類圖

對用戶而言,能夠直接使用的就是綠色的類。併發

經過 RPC 這個門面:socket

  • 客戶端能夠建立相應的 proxy,接着就能夠進行遠程調用。
  • 而服務提供者則能夠建立相應的 server,並進行相應的生命週期管理(start、stop),從而提供服務。

序列化

從上圖也能夠看出,client 和 server 的交互,是經過網絡 connection, 而走網絡的調用,是須要走序列化/反序列話的過程的。oop

這個過程, IPC 使用了 Hadoop 的本身的序列化機制,一切都在 Writable 接口中,只要給定 writable 的 DataOutput 和 DataInput,就可讓 Writable 本身實現序列化。線程

一些問題和思考

  • client 是單例的嗎 —— 能夠理解爲是,但其實不必定。能夠跟蹤 getProxy 的代碼,雖然每次都會新建一個代理對象,但底層的 Client 仍是和 SocketFactory 對應的。通常默認的,都是使用默認的 SocketFactory, 但若是你設置了 "hadoop.rpc.socket.factory.class.default" ,則會有新的Client與你自定義的 SocketFactory 對應。這時候, client 就不是單例的。代理

  • client 與同一個 server 有幾個鏈接 —— 一個 client與一個 server 只有一個鏈接,具體能夠看生成的代理中,有一個 remoteId, 這個 remoteId 是和 client關聯的,client 進行調用的使用,會將此 remoteId 做爲一個 connectionId。所以,通常一個 client 是一個鏈接。server

  • 若是 client 是一個鏈接,那麼對此 client 的調用,不都是串行的嗎? —— 看你怎麼理解了,在用戶層面,也就是 client 調用的方法,是能夠併發的。client 底層是使用一個鏈接來進可能的完成吞吐量。每一個 request 和 response 都會有一個 id 關聯起來。所以一個鏈接上能夠跑滿請求和相應。對象

  • 因爲網絡問題,client調用服務失敗後,有重試機制嗎 —— 在IPC中沒有看到call的重試,須要上層去保證了。可是後面的調用會從新創建鏈接。

  • server 是單例的嗎 —— 不必定。若是你只 getServer 一次的話。建立一個 server 的代價是很是重的。經過上圖你也能夠知道,他須要有一個線程 (Listener)來 accept socket,同時須要一些 Reader線程 來進行 socket 的 read,還有一個 Responder 來進行 socket 的 write,另外,還有若干個 handler線程 來進行業務處理。所以,若是能夠減小 server 的個數,就應該減小 server 個數。

  • 暴露出的服務是否應該是線程安全的 —— 是的,必定要線程安全。server 底層是經過 nio 進行 socket 操做的,所以雖然只有一個線程負責 accept,可是可以支持不少的client鏈接。這些鏈接在到達 server 端以後,頗有可能就會併發執行同一方法(若是你的業務handler不止一個的話)

  • 一個 server 要消耗多少線程資源? —— 讓咱們來算一下,一個 Listener 線程,若干個 Reader 線程(默認1個),若干個 Handler 線程(在 getServer 的時候指定,通常1 - 10個),一個 Responder 線程。若是都按照默認值來計算的話。最少須要 1 + 1 + 1 + 1 = 4 個線程。也許,不該該算多,若是請求量不大的話,這些線程應該都被 blocked 住的。

總結

  • Hadoop 的 IPC 是一個比較輕量級別的 RPC
  • 從代碼來看,只支持 java 進程之間的通訊
  • 從沒有重試機制、一個 Client 只有一個鏈接的機制來看,適合與應用網絡環境較好的場景,適合同機架或者同機房的集羣。

P.S. 看了一下 io 包中,其實有個 retry 的 package,裏面就是一個重試機制。奇怪的是爲啥這個 package 被包含在 io package 中。

相關文章
相關標籤/搜索