Hadoop學習筆記—3.Hadoop RPC機制的使用


一、RPC基礎概念

1.1 RPC的基礎概念

  RPC,即Remote Procdure Call,中文名:遠程過程調用

  (1)它允許一台計算機程序遠程調用另外一台計算機的子程序,而不用去關心底層的網絡通信細節,對我們來說是透明的。因此,它經常用於分布式網絡通信中。

RPC協議假定某些傳輸協議的存在,如TCP或UDP,為通信程序之間攜帶信息數據。在OSI網絡通信模型中,RPC跨越了傳輸層和應用層。RPC使得開發包括網絡分布式多程序在內的應用程序更加容易。

  (2)Hadoop的進程間交互都是通過RPC來進行的,比如Namenode與Datanode直接,Jobtracker與Tasktracker之間等。

因此,可以說:Hadoop的運行就是建立在RPC基礎之上的

1.2 RPC的顯著特點

  (1)透明性:遠程調用其他機器上的程序,對用戶來說就像是調用本地方法一樣;

  (2)高性能:RPC Server能夠並發處理多個來自Client的請求;

  (3)可控性:jdk中已經提供了一個RPC框架—RMI,但是該PRC框架過於重量級並且可控之處比較少,所以Hadoop RPC實現了自定義的PRC框架。

1.3 RPC的基本流程

  (1)RPC采用了C/S的模式;

  (2)Client端發送一個帶有參數的請求信息到Server;

  (3)Server接收到這個請求以后,根據發送過來的參數調用相應的程序,然后把自己計算好的結果發送給Client端;

  (4)Client端接收到結果后繼續運行;

1.4 Hadoop中的RPC機制

  同其他RPC框架一樣,Hadoop RPC分為四個部分:

  (1)序列化層:Clent與Server端通信傳遞的信息采用了Hadoop里提供的序列化類或自定義的Writable類型;

  (2)函數調用層:Hadoop RPC通過動態代理以及java反射實現函數調用;

  (3)網絡傳輸層:Hadoop RPC采用了基於TCP/IP的socket機制;

  (4)服務器端框架層:RPC Server利用java NIO以及采用了事件驅動的I/O模型,提高RPC Server的並發處理能力;

  Hadoop RPC在整個Hadoop中應用非常廣泛,Client、DataNode、NameNode之間的通訊全靠它了。例如:我們平時操作HDFS的時候,使用的是FileSystem類,它的內部有個DFSClient對象,這個對象負責與NameNode打交道。在運行時,DFSClient在本地創建一個NameNode的代理,然后就操作這個代理,這個代理就會通過網絡,遠程調用到NameNode的方法,也能返回值。

1.5 Hadoop RPC設計技術

  (1)動態代理

About:動態代理可以提供對另一個對象的訪問,同時隱藏實際對象的具體事實,代理對象對客戶隱藏了實際對象。目前Java開發包中提供了對動態代理的支持,但現在只支持對接口的實現

  (2)反射——動態加載類

  (3)序列化

  (4)非阻塞的異步IO(NIO)

Java NIO原理請參考閱讀:http://weixiaolu.iteye.com/blog/1479656

二、如何使用RPC

2.1 Hadoop RPC對外提供的接口

  Hadoop RPC對外主要提供了兩種接口(見類org.apache.hadoop.ipc.RPC),分別是:

  (1)public static <T> ProtocolProxy <T> getProxy/waitForProxy(…)

  構造一個客戶端代理對象(該對象實現了某個協議),用於向服務器發送RPC請求。

  (2)public static Server RPC.Builder (Configuration).build()

  為某個協議(實際上是Java接口)實例構造一個服務器對象,用於處理客戶端發送的請求。

2.2 使用Hadoop RPC的四大步湊

  (1)定義RPC協議

  RPC協議是客戶端和服務器端之間的通信接口,它定義了服務器端對外提供的服務接口。

  (2)實現RPC協議

  Hadoop RPC協議通常是一個Java接口,用戶需要實現該接口。

  (3)構造和啟動RPC SERVER

  直接使用靜態類Builder構造一個RPC Server,並調用函數start()啟動該Server。

  (4)構造RPC Client並發送請求

  使用靜態方法getProxy構造客戶端代理對象,直接通過代理對象調用遠程端的方法。

三、RPC應用實例

3.1 定義RPC協議

  如下所示,我們定義一個IProxyProtocol 通信接口,聲明了一個Add()方法。

public interface IProxyProtocol extends VersionedProtocol {
    static final long VERSION = 23234L; //版本號,默認情況下,不同版本號的RPC Client和Server之間不能相互通信
    int Add(int number1,int number2);
}

  需要注意的是:

  (1)Hadoop中所有自定義RPC接口都需要繼承VersionedProtocol接口,它描述了協議的版本信息。

  (2)默認情況下,不同版本號的RPC Client和Server之間不能相互通信,因此客戶端和服務端通過版本號標識。

3.2 實現RPC協議

  Hadoop RPC協議通常是一個Java接口,用戶需要實現該接口。對IProxyProtocol接口進行簡單的實現如下所示:

public class MyProxy implements IProxyProtocol {
    public int Add(int number1,int number2) {
        System.out.println("我被調用了!");
        int result = number1+number2;
        return result;
    }

    public long getProtocolVersion(String protocol, long clientVersion)
            throws IOException {
        System.out.println("MyProxy.ProtocolVersion=" + IProxyProtocol.VERSION);
        // 注意:這里返回的版本號與客戶端提供的版本號需保持一致
        return IProxyProtocol.VERSION;
    }
}

  這里實現的Add方法很簡單,就是一個加法操作。為了查看效果,這里通過控制台輸出一句:“我被調用了!”

3.3 構造RPC Server並啟動服務

  這里通過RPC的靜態方法getServer來獲得Server對象,如下代碼所示:

public class MyServer {
    public static int PORT = 5432;
    public static String IPAddress = "127.0.0.1";

    public static void main(String[] args) throws Exception {
        MyProxy proxy = new MyProxy();
        final Server server = RPC.getServer(proxy, IPAddress, PORT, new Configuration());
        server.start();
    }
}

  這段代碼的核心在於第5行的RPC.getServer方法,該方法有四個參數,第一個參數是被調用的java對象,第二個參數是服務器的地址,第三個參數是服務器的端口 。獲得服務器對象后,啟動服務器。這樣,服務器就在指定端口監聽客戶端的請求。到此為止,服務器就處於監聽狀態,不停地等待客戶端請求到達。

3.4 構造RPC Client並發出請求

  這里使用靜態方法getProxy或waitForProxy構造客戶端代理對象,直接通過代理對象調用遠程端的方法,具體如下所示:

public class MyClient {

    public static void main(String[] args) {
        InetSocketAddress inetSocketAddress = new InetSocketAddress(
                MyServer.IPAddress, MyServer.PORT);

        try {
            // 注意:這里傳入的版本號需要與代理保持一致
            IProxyProtocol proxy = (IProxyProtocol) RPC.waitForProxy(
                    IProxyProtocol.class, IProxyProtocol.VERSION, inetSocketAddress,
                    new Configuration());
            int result = proxy.Add(10, 25);
            System.out.println("10+25=" + result);

            RPC.stopProxy(proxy);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

  以上代碼中核心在於RPC.waitForProxy(),該方法有四個參數,第一個參數是被調用的接口類,第二個是客戶端版本號,第三個是服務端地址。返回的代理對象,就是服務端對象的代理,內部就是使用java.lang.Proxy實現的。

  經過以上四步,我們便利用Hadoop RPC搭建了一個非常高效的客戶機–服務器網絡模型。

3.5 查看運行結果

  (1)啟動服務端,開始監聽客戶端請求

  (2)啟動客戶端,開始向服務端發請求

  (3)查看服務端狀態,是否被調用

SUMMARY:從上面的RPC調用中,可以看出:在客戶端調用的業務類的方法是定義在業務類的接口中的。該接口實現了VersionedProtocal接口

  (4)現在我們在命令行執行jps命令,查看輸出信息,會出現如下圖所示的:

  從上圖中可以看到一個java進程,是“MyServer”,該進程正是我們剛剛運行的RPC的服務端類MyServer。因此,大家可以聯想到我們搭建Hadoop環境時,也執行過該命令用來判斷Hadoop的相關進程是否全部啟動。

SUMMARY:那么可以判斷,Hadoop啟動時產生的5個java進程也應該是RPC的服務端。  

  下面我們觀察NameNode的源代碼,如下圖所示,可以看到NameNode確實創建了RPC的服務端。

private void initialize(Configuration conf) throws IOException {
    ......
    // create rpc server
    InetSocketAddress dnSocketAddr = getServiceRpcServerAddress(conf);
    if (dnSocketAddr != null) {
      int serviceHandlerCount =
        conf.getInt(DFSConfigKeys.DFS_NAMENODE_SERVICE_HANDLER_COUNT_KEY,
                    DFSConfigKeys.DFS_NAMENODE_SERVICE_HANDLER_COUNT_DEFAULT);
      this.serviceRpcServer = RPC.getServer(this, dnSocketAddr.getHostName(), 
          dnSocketAddr.getPort(), serviceHandlerCount,
          false, conf, namesystem.getDelegationTokenSecretManager());
      this.serviceRPCAddress = this.serviceRpcServer.getListenerAddress();
      setRpcServiceServerAddress(conf);
    }
    this.server = RPC.getServer(this, socAddr.getHostName(),
        socAddr.getPort(), handlerCount, false, conf, namesystem
        .getDelegationTokenSecretManager());
   ......
}

參考資料

(1)thomas0yang,《Hadoop RPC框架》:http://blog.csdn.net/thomas0yang/article/details/41211259

(2)姜維,《Hadoop RPC機制分析》:http://blog.csdn.net/jiangwei0910410003/article/details/21155911 (此文從源碼角度分析了RPC,想要深入了解的可以閱讀此文)

(3)吳超,《Hadoop的底層架構—RPC機制》:http://www.superwu.cn/2013/08/05/360

(4)東苑草根,《Hadoop RPC基礎》:http://www.cnblogs.com/dycg/p/rpc.html

(5)Suddenly,《Hadoop日記Day10-RPC機制》:http://www.cnblogs.com/sunddenly/p/3983193.html

(6)董西成,《Hadoop RPC使用方法》:http://book.51cto.com/art/201312/422043.htm

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM