您好,登錄后才能下訂單哦!
[TOC]
? 所謂的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)用者是在同一臺主機上的,但是實際上是在不同主機上的。
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)用者作為返回值。
hdfs的rpc流程基本如上,其中的關(guān)鍵就是獲得NameNode代理對象。
(1)靜態(tài)代理
先定義一個公共接口,里面包括了可以通過RPC調(diào)用的方法列表。而且被代理對象以及對象本身都需要實現(xiàn)該接口
(2)動態(tài)代理
先定義一個公共接口,里面包括了可以通過RPC調(diào)用的方法列表。被代理對象以及對象本身都不需要實現(xiàn)該接口。而是通過匿名內(nèi)部類+反射的機制實現(xiàn)。hadoop就是使用這種方式
例子結(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
免責(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)容。