溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

六、RPC基本原理

發(fā)布時間:2020-06-26 19:18:56 來源:網(wǎng)絡(luò) 閱讀:216 作者:隔壁小白 欄目:大數(shù)據(jù)

[TOC]

一、RPC基本概念

1、RPC是什么

? 所謂的RPC其實是為了不同主機的兩個進(jìn)程間通信而產(chǎn)生的,通常不同的主機之間的進(jìn)程通信,那么程序編寫則需要考慮到網(wǎng)絡(luò)通信的功能,這樣程序的編寫將會變得復(fù)雜。而RPC就是報文交換的一種機制,一臺主機上的進(jìn)程對另外一臺主機的進(jìn)程發(fā)起請求時,內(nèi)核會將請求轉(zhuǎn)交給RPC client,RPC client經(jīng)過報文的封裝轉(zhuǎn)交給目標(biāo)主機的RPC server,RPC server就將報文進(jìn)行解析,還原成正常的請求,轉(zhuǎn)交給目標(biāo)主機上的目標(biāo)進(jìn)程。所以在兩臺主機的兩個進(jìn)程看來,就像是在同一臺主機上的兩個進(jìn)程通信一樣,完全沒有意識到是在不同的主機上。所以說RPC其實也是一種協(xié)議或者是編程框架,簡化了分布式程序的編寫。
? 而hadoop作為一個典型的分布式項目,跨主機調(diào)用服務(wù)的情況很常見(并非http服務(wù))。我們要清楚一點,通過http這些restfulapi的方式暴露的服務(wù),調(diào)用者是明顯知道被調(diào)用者是在不同的主機上。而通過RPC調(diào)用的話,在調(diào)用者看來,他以為被調(diào)用者是在同一臺主機上的,但是實際上是在不同主機上的。

2、RPC基本流程

六、RPC基本原理

1、首先調(diào)用方需要有個RPCclient,被調(diào)用方需要有 RCPServer,這兩個服務(wù)用于RPC通信。
2、調(diào)用者通過RPCClient調(diào)用指定方法,RPCClient則將請求封裝后(將方法參數(shù)值進(jìn)行二進(jìn)制序列化),傳遞給server
3、server收到請求后,反序列化參數(shù),恢復(fù)成請求原本的形式,然后找到對應(yīng)的方法進(jìn)行本地調(diào)用。將方法的返回值通過RPC返回給client
4、client收到結(jié)果后,將結(jié)果返回給調(diào)用者作為返回值。

二、hadoop的RPC

1、hdfs的RPC基本流程

六、RPC基本原理

hdfs的rpc流程基本如上,其中的關(guān)鍵就是獲得NameNode代理對象。

2、java中的代理方式

(1)靜態(tài)代理
先定義一個公共接口,里面包括了可以通過RPC調(diào)用的方法列表。而且被代理對象以及對象本身都需要實現(xiàn)該接口

(2)動態(tài)代理
先定義一個公共接口,里面包括了可以通過RPC調(diào)用的方法列表。被代理對象以及對象本身都不需要實現(xiàn)該接口。而是通過匿名內(nèi)部類+反射的機制實現(xiàn)。hadoop就是使用這種方式

3、hadoop rpc框架的例子

例子結(jié)構(gòu):

Server
    MyImpl.java         server本地執(zhí)行的方法的具體實現(xiàn)代碼
    MyInterface.java    可以rpc執(zhí)行的方法列表
    MyRpcServer.java    rpc server端
Client
    MyRpcClient.java    rpc client端

Server:

/*
MyInterface.java    
*/
package Server;

import org.apache.hadoop.ipc.VersionedProtocol;

public interface MyInterface extends VersionedProtocol {
    public static long versionID = 1001; //這個是標(biāo)記RPC的client和server對應(yīng)的標(biāo)記
    public String helloWorld(String name);
}

/*
MyImpl.java
*/
package Server;

import org.apache.hadoop.ipc.ProtocolSignature;

import java.io.IOException;

public class MyImpl implements MyInterface{
    /*這是實際目標(biāo)*/

    //重寫我們在上面接口自定義的方法
    @Override
    public String helloWorld(String name) {
        return "hello," + name;
    }

    //返回版本號
    @Override
    public long getProtocolVersion(String s, long l) throws IOException {
        return MyInterface.versionID;
    }

    //返回簽名信息
    @Override
    public ProtocolSignature getProtocolSignature(String s, long l, int i) throws IOException {
        return new ProtocolSignature(MyInterface.versionID, null);
    }
}

/*
MyRpcServer.java
*/
package Server;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ipc.RPC;

import java.io.IOException;

public class MyRpcServer {
    public static void main(String[] args) {
        //建立rpc通道對象
        RPC.Builder builder = new RPC.Builder(new Configuration());

        //設(shè)置RPC server參數(shù)
        builder.setBindAddress("localhost");
        builder.setPort(7788);

        //部署程序,傳入實現(xiàn)server業(yè)務(wù)代碼的接口定義,這里面包括了該rpcserver 可以提供的方法,也就是給client調(diào)用的方法列表,通過反射的方式引入類對象
        builder.setProtocol(MyInterface.class);

        //部署接口的實現(xiàn)類對象
        builder.setInstance(new MyImpl());

        //開啟server
        try {
            RPC.Server server = builder.build();
            server.start();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

client:

/*
MyRpcClient.java
*/
package Client;

import Server.MyInterface;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ipc.RPC;

import java.io.IOException;
import java.net.InetSocketAddress;

public class MyRpcClient {
    public static void main(String[] args) {
        try {
            //獲取代理對象,設(shè)置接口類對象、RPC通信的versionID,rpcserver地址、configuration對象
            MyInterface proxy = RPC.getProxy(
                    MyInterface.class,
                    MyInterface.versionID,
                    new InetSocketAddress("localhost", 7788),
                    new Configuration());

            //獲得代理對象之后,就可以通過proxy調(diào)用接口類中的方法,這里就調(diào)用上面定義的 helloWorld對象
            System.out.println(proxy.helloWorld("king"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

下面啟動server端和client端,執(zhí)行結(jié)果為:

//server:可以看到顯示監(jiān)聽端口 7788
[main] INFO org.apache.hadoop.ipc.CallQueueManager - Using callQueue: class java.util.concurrent.LinkedBlockingQueue queueCapacity: 100 scheduler: class org.apache.hadoop.ipc.DefaultRpcScheduler
[Socket Reader #1 for port 7788] INFO org.apache.hadoop.ipc.Server - Starting Socket Reader #1 for port 7788
[IPC Server Responder] INFO org.apache.hadoop.ipc.Server - IPC Server Responder: starting
[IPC Server listener on 7788] INFO org.apache.hadoop.ipc.Server - IPC Server listener on 7788: starting

//client:  我們傳入“King”作為參數(shù),能夠爭取執(zhí)行
hello,king
向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI