最近開始看 Hadoop 的一些源碼,展開 hadoop 的源碼包,各個組件分得比較清楚,因而開始看一下 IPC 的一些源碼。(版本是 1.0.4 中的 ipc 包,多謝 @上古進程 提醒)java
IPC模塊,也就是 進程間通訊模塊,若是是在不一樣的機器上,那就能夠理解爲 RPC 了,也就是遠程調用。事實上, hadoop 中的 IPC 也就是基於 RPC 實現的。安全
使用 sloccount 統計一下 ipc 包中代碼的行數,一共是 2884 行。也就是說,IPC 做爲hadoop的基礎組件,僅僅用了不到3000行的代碼,就完成得穩定且富有效率。網絡
對用戶而言,能夠直接使用的就是綠色的類。併發
經過 RPC 這個門面:socket
從上圖也能夠看出,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 住的。
P.S. 看了一下 io 包中,其實有個 retry 的 package,裏面就是一個重試機制。奇怪的是爲啥這個 package 被包含在 io package 中。