码迷,mamicode.com
首页 > 其他好文 > 详细

Hadoop的RPC

时间:2019-01-01 11:43:31      阅读:190      评论:0      收藏:0      [点我收藏+]

标签:rpc   ext   模型   你好   加载   三层   完美   配置   try   

1. 关于RPC

(1)RPC的概念

   RPC(Remote Procedure Call)--远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如;TCP或者UDP,为通信程序之间携带信息数据,在OSI网络通信模型中,RPC跨越了传输层应用层。RPC使得开发包括网络分布式程序在内的应用程序更加容易。

(2)OSI网络七层模型

技术分享图片
第一层:物理层。这一层主要就是传输这些二进制数据。
第二层:链路层。将上面的网络层的数据包封装成数据帧,便于物理层传输;
第三层:网络层。定义网络设备间如何传输数据;
第四层:传输层。管理着网络中的端到端的数据传输;
第五层:会话层。管理用户的会话,控制用户间逻辑连接的建立和中断;
第六层:表示层。定义不同的系统中数据的传输格式,编码和解码规范等;
第七层:应用层。定义了用于在网络中进行通信和传输数据的接口;

(3)RPC工作机制

   RPC 采用客户机/服务器模式:请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在 服务器端,进程保持睡眠状态直到调用信息到达为止。当一个调用信息到达,服务器获得进 程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收 答复信息,获得进程结果,然后调用执行继续进行。
   通俗的说: RPC 是指远程过程调用,也就是说两台服务器 A,B,一个应用部署在 A 服务器, 想要调用 B 服务器提供的函数和方法,由于不在一个内存空间,不能直接调用,需要通过 网络来表达调用的语义和传达调用的数据。也可以理解成不同进程之间的服务调用。
     技术分享图片
实现的具体步骤
  第一(通讯问题):主要是通过在客户端和服务器之间建立 TCP 连接,远程过程调用的所有交换的数据都在这个连接里传输。连接可以是按需连接,调用结束后就断掉,也可以是长连接,多个远程过程调用共享同一个连接。
  第二(寻址问题):A 服务器上的应用怎么告诉底层的 RPC 框架,如何连接到 B 服务器(如主机或 IP 地址)以及特定的端口,方法的名称以及名称是什么,这样才能完成调用。
  第三(方法参数的网络传递):当 A 服务器上的应用发起远程过程调用时,方法的参数需要通过底层的网络协议如 TCP 传递到 B 服务器,由于网络协议是基于二进制的,内存中的参数的值要序列化成二进制 的形式,也就是序列化(Serialize)或编组(marshal),通过寻址和传输将序列化的二进制 发送给 B 服务器。
  第四(反序列化):B 服务器收到请求后,需要对参数进行反序列化(序列化的逆操作),恢复为内存中 的表达方式,然后找到对应的方法(寻址的一部分)进行本地调用,然后得到返回值。
  第五(返回值):返回值还要发送回服务器 A 上的应用,也要经过序列化的方式发送,服务器 A 接到 后,再反序列化,恢复为内存中的表达方式,交给 A 服务器上的应用

(4)RPC的作用

   - 让调用方感觉就像调用本地函数一样调用远端函数、让服务提供方感觉就像实现一个本地函数一样来实现服务,并且屏蔽编程语言的差异性。
   - 让构建分布式计算(应用)更容易,在提供强大的远程调用能力时不损失本地调用的语义简洁性
   - 在客户端 A 上来说,会生成一个服务器 B 的代理。(总结)

(5)JAVA中流行的RPC框架

  RMI(远程方法调用):JAVA 自带的远程方法调用工具,不过有一定的局限性,毕竟是 JAVA 语言最开始时的设计, 后来很多框架的原理都基于 RMI。
  Hessian(基于 HTTP 的远程方法调用):基于 HTTP 协议传输,在性能方面还不够完美,负载均衡和失效转移依赖于应用的负载均衡 器,Hessian 的使用则与 RMI 类似,区别在于淡化了 Registry 的角色,通过显示的地址调用, 利用 HessianProxyFactory 根据配置的地址 create 一个代理对象,另外还要引入 Hessian 的 Jar 包。
  Dubbo(阿里开源的基于 TCP 的 RPC 框架):基于 Netty 的高性能 RPC 框架。
       技术分享图片

2. Hadoop的RPC

(1)相关概念介绍

  同其他 RPC 框架一样,Hadoop RPC 分为四个部分:
   - 序列化层:Client 与 Server 端通信传递的信息采用了 Hadoop 里提供的序列化类或自定义 的 Writable 类型;
   - 函数调用层:Hadoop RPC 通过动态代理以及 Java 反射实现函数调用;
   - 网络传输层:Hadoop RPC 采用了基于 TCP/IP 的 socket 机制;
   - 服务器端框架层:RPC Server利用Java NIO以及采用了事件驱动的I/O模型,提高RPC Server 的并发处理能力;
  Hadoop RPC 在整个 Hadoop 中应用非常广泛,Client、DataNode、NameNode 之间的通讯全 靠它了。例如:我们平时操作 HDFS 的时候,使用的是 FileSystem 类,它的内部有个 DFSClient 对象,这个对象负责与 NameNode 打交道。在运行时,DFSClient 在本地创建一个 NameNode 的代理,然后就操作这个代理,这个代理就会通过网络,远程调用到 NameNode 的方法, 也能返回值。
        技术分享图片

(2)涉及到的相关技术点

  - 代理:动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实,代理对 象对客户隐藏了实际对象。目前 Java 开发包中提供了对动态代理的支持,但现在只支持对 接口的实现。
  - 反射:动态加载类
  - 序列化:用于将对象进行网络传输
  - NIO:非阻塞的异步

(3)HadoopRPC的构建步骤

  - 定义PRC协议:RPC 协议是客户端和服务器端之间的通信接口,它定义了服务器端对外提供的服务接口。
  - 实现PRC协议:Hadoop RPC 协议通常是一个 Java 接口,用户需要实现该接口。
  - 构造和启动RPC server :直接使用静态类 Builder 构造一个 RPC Server,并调用函数 start()启动该 Server。
  - 构建RPC client 并发送请求:使用静态方法 getProxy 构造客户端代理对象,直接通过代理对象调用远程端的方法。

(3)HadoopRPC 入门案例

  1.定义协议
//定义PRC协议

public interface BussinessProtocol {
    //在client和server通信的时候,需要版本一致
    long versionID=11511056056L;
    void mkdir(String name);
    void hello(String message);
}

  2.实现协议

//实现RPC协议
public class BussinessProtocolImpl implements BussinessProtocol {

    @Override
    public void mkdir(String name) {
        System.out.println("创建了:"+name);
    }

    @Override
    public void hello(String message) {
        System.out.println("你好"+message);
    }
}

  3.构建服务端

//构建RPCserver并启动服务端
public class MyRPCServer {
    public static void main(String[] args) {
        RPC.Server server = null;
        try {
            /**
             * 在new RPC.Builder:传入Configuration对象
             *  setProtocol(BussinessProtocol.class):设置协议类
             *  setInstance(new BussinessProtocolImpl()):协议实现类对象
             *  setBindAddress("localhost"):绑定的主机
             *  setPort(6789):设置端口
             */
            server = new RPC.Builder(new Configuration())
                    .setProtocol(BussinessProtocol.class)
                    .setInstance(new BussinessProtocolImpl())
                    .setBindAddress("localhost")
                    .setPort(6666)
                    .build();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //启动服务
        server.start();
    }
}

  4.构建客户端
//构建 RPC Client 并发出请求

public class MyRPCClient {
    public static void main(String[] args) {
        try {
            /**
             * 获取代理类对象,客户端通过这个代理可以调用服务端的方法进行逻辑处理:
             * Class<T> protocol 协议类的class对象
             * long clientVersion:版本
             * InetSocketAddress addr:主机端口
             * Configuration conf:配置文件对象
             */
            BussinessProtocol proxy = RPC.getProxy(BussinessProtocol.class,
                    BussinessProtocol.versionID,
                    new InetSocketAddress("localhost", 6666),
                    new Configuration());
            //在客户端调用了服务端的代理对象的方法
            //其实正真的代码在服务端运行
            proxy.hello("zs");
            proxy.mkdir("/root/zy");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

  5.启动测试
启动服务端:运行:
技术分享图片
启动客户端 运行:
技术分享图片
观察服务端console:
技术分享图片

Hadoop的RPC

标签:rpc   ext   模型   你好   加载   三层   完美   配置   try   

原文地址:http://blog.51cto.com/14048416/2337498

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!