一、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()方法。

  1. public interface IProxyProtocol extends VersionedProtocol {
  2. static final long VERSION = 23234L; //版本号,默认情况下,不同版本号的RPC Client和Server之间不能相互通信
  3. int Add(int number1,int number2);
  4. }

  需要注意的是:

  (1)Hadoop中所有自定义RPC接口都需要继承VersionedProtocol接口,它描述了协议的版本信息。

  (2)默认情况下,不同版本号的RPC Client和Server之间不能相互通信,因此客户端和服务端通过版本号标识。

3.2 实现RPC协议

  Hadoop RPC协议通常是一个Java接口,用户需要实现该接口。对IProxyProtocol接口进行简单的实现如下所示:

  1. public class MyProxy implements IProxyProtocol {
  2. public int Add(int number1,int number2) {
  3. System.out.println("我被调用了!");
  4. int result = number1+number2;
  5. return result;
  6. }
  7.  
  8. public long getProtocolVersion(String protocol, long clientVersion)
  9. throws IOException {
  10. System.out.println("MyProxy.ProtocolVersion=" + IProxyProtocol.VERSION);
  11. // 注意:这里返回的版本号与客户端提供的版本号需保持一致
  12. return IProxyProtocol.VERSION;
  13. }
  14. }

  这里实现的Add方法很简单,就是一个加法操作。为了查看效果,这里通过控制台输出一句:“我被调用了!”

3.3 构造RPC Server并启动服务

  这里通过RPC的静态方法getServer来获得Server对象,如下代码所示:

  1. public class MyServer {
  2. public static int PORT = 5432;
  3. public static String IPAddress = "127.0.0.1";
  4.  
  5. public static void main(String[] args) throws Exception {
  6. MyProxy proxy = new MyProxy();
  7. final Server server = RPC.getServer(proxy, IPAddress, PORT, new Configuration());
  8. server.start();
  9. }
  10. }

  这段代码的核心在于第5行的RPC.getServer方法,该方法有四个参数,第一个参数是被调用的java对象,第二个参数是服务器的地址,第三个参数是服务器的端口 。获得服务器对象后,启动服务器。这样,服务器就在指定端口监听客户端的请求。到此为止,服务器就处于监听状态,不停地等待客户端请求到达。

3.4 构造RPC Client并发出请求

  这里使用静态方法getProxy或waitForProxy构造客户端代理对象,直接通过代理对象调用远程端的方法,具体如下所示:

  1. public class MyClient {
  2.  
  3. public static void main(String[] args) {
  4. InetSocketAddress inetSocketAddress = new InetSocketAddress(
  5. MyServer.IPAddress, MyServer.PORT);
  6.  
  7. try {
  8. // 注意:这里传入的版本号需要与代理保持一致
  9. IProxyProtocol proxy = (IProxyProtocol) RPC.waitForProxy(
  10. IProxyProtocol.class, IProxyProtocol.VERSION, inetSocketAddress,
  11. new Configuration());
  12. int result = proxy.Add(10, 25);
  13. System.out.println("10+25=" + result);
  14.  
  15. RPC.stopProxy(proxy);
  16. } catch (IOException e) {
  17. // TODO Auto-generated catch block
  18. e.printStackTrace();
  19. }
  20. }
  21.  
  22. }

  以上代码中核心在于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的服务端。

  1. private void initialize(Configuration conf) throws IOException {
  2. ......
  3. // create rpc server
  4. InetSocketAddress dnSocketAddr = getServiceRpcServerAddress(conf);
  5. if (dnSocketAddr != null) {
  6. int serviceHandlerCount =
  7. conf.getInt(DFSConfigKeys.DFS_NAMENODE_SERVICE_HANDLER_COUNT_KEY,
  8. DFSConfigKeys.DFS_NAMENODE_SERVICE_HANDLER_COUNT_DEFAULT);
  9. this.serviceRpcServer = RPC.getServer(this, dnSocketAddr.getHostName(),
  10. dnSocketAddr.getPort(), serviceHandlerCount,
  11. false, conf, namesystem.getDelegationTokenSecretManager());
  12. this.serviceRPCAddress = this.serviceRpcServer.getListenerAddress();
  13. setRpcServiceServerAddress(conf);
  14. }
  15. this.server = RPC.getServer(this, socAddr.getHostName(),
  16. socAddr.getPort(), handlerCount, false, conf, namesystem
  17. .getDelegationTokenSecretManager());
  18. ......
  19. }

参考资料

(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

作者:周旭龙

出处:http://edisonchou.cnblogs.com/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

Hadoop学习笔记—3.Hadoop RPC机制的使用的更多相关文章

  1. [转帖]hadoop学习笔记:hadoop文件系统浅析

    hadoop学习笔记:hadoop文件系统浅析 https://www.cnblogs.com/sharpxiajun/archive/2013/06/15/3137765.html 1.什么是分布式 ...

  2. Hadoop学习笔记【Hadoop家族成员概述】

    Hadoop家族成员概述 一.Hadoop简介 1.1 什么是Hadoop? Hadoop是一个分布式系统基础架构,由Apache基金会所开发,目前Yahoo!是其最重要的贡献者. Hadoop实现了 ...

  3. [Hadoop] Hadoop学习笔记之Hadoop基础

    1 Hadoop是什么? Google公司发表了两篇论文:一篇论文是“The Google File System”,介绍如何实现分布式地存储海量数据:另一篇论文是“Mapreduce:Simplif ...

  4. Hadoop学习笔记(3) Hadoop文件系统二

    1 查询文件系统 (1) 文件元数据:FileStatus,该类封装了文件系统中文件和目录的元数据,包括文件长度.块大小.备份.修改时间.所有者以及版权信息.FileSystem的getFileSta ...

  5. Hadoop学习笔记(3) Hadoop文件系统一

    1. 分布式文件系统,即为管理网络中跨多台计算机存储的文件系统.HDFS以流式数据访问模式来存储超大文件,运行于商用硬件集群上.HDFS的构建思路为:一次写入.多次读取是最高效的访问模式.数据集通常由 ...

  6. 吴裕雄--天生自然HADOOP学习笔记:hadoop集群实现PageRank算法实验报告

    实验课程名称:大数据处理技术 实验项目名称:hadoop集群实现PageRank算法 实验类型:综合性 实验日期:2018年 6 月4日-6月14日 学生姓名 吴裕雄 学号 15210120331 班 ...

  7. 吴裕雄--天生自然Hadoop学习笔记:Hadoop简介

    Hadoop是一个由Apache基金会所开发的分布式系统基础架构.用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群的威力进行高速运算和存储.Hadoop实现了一个分布式文件系统(H ...

  8. Hadoop学习笔记—6.Hadoop Eclipse插件的使用

    开篇:Hadoop是一个强大的并行软件开发框架,它可以让任务在分布式集群上并行处理,从而提高执行效率.但是,它也有一些缺点,如编码.调试Hadoop程序的难度较大,这样的缺点直接导致开发人员入门门槛高 ...

  9. Hadoop学习笔记(3) Hadoop I/O

    1. HDFS的数据完整性 HDFS会对写入的所有数据计算校验和,并在读取数据时验证校验和.datanode负责在验证收到的数据后存储数据及其校验和.正在写数据的客户端将数据及其校验和发送到由一系列d ...

随机推荐

  1. 一次mongodb 统计需求

    需求: 临下班运营的同事发来了一个需求,要统计数据库里某个collection的所有document 中某个字段(_id)出现的次数._id 字段的范围是0-4000. 假设collection 是这 ...

  2. ssh反向连接和简单实现

    转自:http://blog.chinaunix.net/uid-20109107-id-2954579.html SSH反向连接的使用 1.什么是反向连接?反向连接是指主机A(受控端)主动连接主机B ...

  3. XSS之xssprotect(转)

    参考资料 1 跨网站脚本 http://zh.wikipedia.org/wiki/XSS 2 http://code.google.com/p/xssprotect/ 一 跨网站脚本介绍      ...

  4. SpringMVC(一) SpringMVC概述

    SpringMVC为展现层提供的基于MVC设计理念的优秀的WEB框架,是目前主流的MVC框架之一.Spring 3.0之后,超越Struts2成为最优秀的MVC框架. SpringMVC通过一套MVC ...

  5. Swift 基本常量和变量,基本数据类型

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Menlo; color: #4dbf56 } p.p2 { margin: 0.0px 0. ...

  6. Linux中安装NodeJs 、cnpm 、npm

    一.安装NodeJs 切换到 cd /usr/local/src/ 下载nodejs wget https://nodejs.org/dist/v6.9.3/node-v6.9.3-linux-x64 ...

  7. js判断当前页面在移动设备还是在PC端中打开

    方法一: var isPC = function () { var userAgentInfo = navigator.userAgent.toLowerCase(); var Agents = ne ...

  8. IO(1)

    java的IO主要在java.io包下,包括字节流和字符流. 1 File File类可以对文件和目录进行操作,就是不能访问文件本身,其常用方法包括: 1)String getName(),返回fil ...

  9. Lua 排行榜更新

    排行榜: key:玩家名字,val:玩家的数值 local key1 = {"a1", "a2", "b1", "b2" ...

  10. 解决ugui中Image使用iTween的ColorTo、ColorFrom等不生效

    查看iTween的源码找到ColorFrom函数,看该函数的注释“/// Changes a GameObject's color values instantly then returns them ...