一、RPC概述
RPC是指遠端程序呼叫, 也就是說兩台不同的伺服器(不受作業系統限制), 一個應用部署在Linux-A上, 一個應用部署在Windows-B或Linux-B上, 若A想要調用B上的某個方法method, 由於不在一個記憶體空間, 不能直接調用, 需要通過網路來表達調用的語意和傳達調用的參數。
樓主在接觸RPC之前, 用得最多的莫過於WebService。 WebService可以說是在RPC發展的基礎之上。 RPC的協議有很多, 比如最早的CORBA, Java RMI,Web Service等, 又比如現在阿裡巴巴的Dubbo, Apache下的hadoop項目。 該篇樓主主要以hadoop的RPC為例。
hadoop為何要使用RPC?在HDFS中, 我們通過jsp可查看到有DataNode,NameNode,SecondaryNameNode主要進程(樓主只啟動了HDFS), 我們用戶端Client與NameNode通信, NameNode與DataNode的通信, 都是在不同進程間,
二、RPC流程
通過下圖, 我們簡單分析RPC的執行流程:
首先, 要解決通訊的問題, 主要是通過在Client和Server之間建立TCP連接, 遠端程序呼叫的所有交換的資料都在這個連接裡傳輸。 連接可以是按需連接, 調用結束後就斷掉, 也可以是長連接,
第二, 要解決定址的問題, 也就是說, A伺服器上的應用怎麼告訴底層的RPC框架, 如何連接到B伺服器(如主機或IP位址)以及特定的埠, 方法的名稱名稱是什麼, 這樣才能完成調用。
第三, 當Client上的應用發起遠端程序呼叫時, 方法的參數需要通過底層的網路通訊協定如TCP傳遞到Server, 由於網路通訊協定是基於二進位的, 記憶體中的參數的值要序列化成二進位的形式, 也就是序列化(Serialize), 通過定址和傳輸將序列化的二進位發送給B伺服器。
第四, Server收到請求後, 需要對參數進行反序列化(序列化的逆操作), 恢復為記憶體中的表達方式, 然後找到對應的方法(定址的一部分)進行本地調用, 然後得到返回值。
三、hadoop—RPC的簡單使用
定義介面Bizable:
1 package cn.jon.hadoop.rpc; 2 3 public interface MyBizable { 4 long versionID = 123456;//該欄位必須要有, 不然會報java.lang.NoSuchFieldException: versionID異常 5 public String doSomething(String str); 6 }服務端RPCServer實現MyBizable介面並綁定IP位址及埠號:
package cn.jon.hadoop.rpc; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.ipc.RPC; import org.apache.hadoop.ipc.Server; public class RPCServer implements MyBizable { @Override public String doSomething(String str) { return str; } /** * @param args * @throws Exception * @throws */ public static void main(String[] args) throws Exception { Server server = new RPC.Builder(new Configuration) .setProtocol(MyBizable.class) .setInstance(new RPCServer) .setBindAddress("192.168.8.100") .setPort(8077) .build; server.start; } }用戶端RPCClient:
package cn.jon.hadoop.rpc; import java.net.InetSocketAddress; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.ipc.RPC; public class RPCClient { /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { // TODO Auto-generated method stub MyBizable proxy = RPC.getProxy(MyBizable.class, 123456,new InetSocketAddress("192.168.8.100", 8077) , new Configuration); String result = proxy.doSomething("服務端"); System.out.println(result); RPC.stopProxy(proxy); } }樓主使用Linux作為用戶端, Windows作為服務端, 我們先把寫好的程式打成jar, 上傳到Linux:
然後, 我們在windows端啟動RPCServer:
服務端啟動好後, 我們在Linux中執行RPCClient.jar:
java -jar RPCClient.jar執行結果可以看到輸出了“服務端”(樓主Linux時間沒有調準確):
下篇樓主將對HDFS原理進行探討, 到時會更加詳細的討論RPC。