千家信息网

六、RPC基本原理

发表于:2025-01-28 作者:千家信息网编辑
千家信息网最后更新 2025年01月28日,[TOC]一、RPC基本概念1、RPC是什么​ 所谓的RPC其实是为了不同主机的两个进程间通信而产生的,通常不同的主机之间的进程通信,那么程序编写则需要考虑到网络通信的功能,这样程序的编写将会变得复杂
千家信息网最后更新 2025年01月28日六、RPC基本原理

[TOC]

一、RPC基本概念

1、RPC是什么

​ 所谓的RPC其实是为了不同主机的两个进程间通信而产生的,通常不同的主机之间的进程通信,那么程序编写则需要考虑到网络通信的功能,这样程序的编写将会变得复杂。而RPC就是报文交换的一种机制,一台主机上的进程对另外一台主机的进程发起请求时,内核会将请求转交给RPC client,RPC client经过报文的封装转交给目标主机的RPC server,RPC server就将报文进行解析,还原成正常的请求,转交给目标主机上的目标进程。所以在两台主机的两个进程看来,就像是在同一台主机上的两个进程通信一样,完全没有意识到是在不同的主机上。所以说RPC其实也是一种协议或者是编程框架,简化了分布式程序的编写。
​ 而hadoop作为一个典型的分布式项目,跨主机调用服务的情况很常见(并非http服务)。我们要清楚一点,通过http这些restfulapi的方式暴露的服务,调用者是明显知道被调用者是在不同的主机上。而通过RPC调用的话,在调用者看来,他以为被调用者是在同一台主机上的,但是实际上是在不同主机上的。

2、RPC基本流程

1、首先调用方需要有个RPCclient,被调用方需要有 RCPServer,这两个服务用于RPC通信。
2、调用者通过RPCClient调用指定方法,RPCClient则将请求封装后(将方法参数值进行二进制序列化),传递给server
3、server收到请求后,反序列化参数,恢复成请求原本的形式,然后找到对应的方法进行本地调用。将方法的返回值通过RPC返回给client
4、client收到结果后,将结果返回给调用者作为返回值。

二、hadoop的RPC

1、hdfs的RPC基本流程

hdfs的rpc流程基本如上,其中的关键就是获得NameNode代理对象。

2、java中的代理方式

(1)静态代理
先定义一个公共接口,里面包括了可以通过RPC调用的方法列表。而且被代理对象以及对象本身都需要实现该接口

(2)动态代理
先定义一个公共接口,里面包括了可以通过RPC调用的方法列表。被代理对象以及对象本身都不需要实现该接口。而是通过匿名内部类+反射的机制实现。hadoop就是使用这种方式

3、hadoop rpc框架的例子

例子结构:

Server    MyImpl.java         server本地执行的方法的具体实现代码    MyInterface.java    可以rpc执行的方法列表    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; //这个是标记RPC的client和server对应的标记    public String helloWorld(String name);}/*MyImpl.java*/package Server;import org.apache.hadoop.ipc.ProtocolSignature;import java.io.IOException;public class MyImpl implements MyInterface{    /*这是实际目标*/    //重写我们在上面接口自定义的方法    @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());        //设置RPC server参数        builder.setBindAddress("localhost");        builder.setPort(7788);        //部署程序,传入实现server业务代码的接口定义,这里面包括了该rpcserver 可以提供的方法,也就是给client调用的方法列表,通过反射的方式引入类对象        builder.setProtocol(MyInterface.class);        //部署接口的实现类对象        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 {            //获取代理对象,设置接口类对象、RPC通信的versionID,rpcserver地址、configuration对象            MyInterface proxy = RPC.getProxy(                    MyInterface.class,                    MyInterface.versionID,                    new InetSocketAddress("localhost", 7788),                    new Configuration());            //获得代理对象之后,就可以通过proxy调用接口类中的方法,这里就调用上面定义的 helloWorld对象            System.out.println(proxy.helloWorld("king"));        } catch (IOException e) {            e.printStackTrace();        }    }}

下面启动server端和client端,执行结果为:

//server:可以看到显示监听端口 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"作为参数,能够争取执行hello,king
0