A-A+

从零学习Hadoop之Hadoop的RPC机制

2016年04月05日 Hadoop 评论 1 条 阅读 513 views 次

说在前面的话

一般我们说了解的RPC(Remote Procedure Call,远程过程调用)机制都要面对两个问题:

  1. 对象调用方式;
  2. 序列/反序列化机制。

RPC架构如图所示:

RPC

Hadoop自己实现了简单的RPC组件,依赖于Hadoop Writable类型的支持。

Hadoop Writable接口要求每个实现类都要确保将本类的对象正确序列化(writeObject)与反序列化(readObject)。因此,Hadoop RPC使用Java动态代理与反射实现对象的调用方式(对应上述问题1),客户端到服务器数据的序列化与反序列化由Hadoop框架或者用户自己来实现,也就是数据组装是定制的(根据需求继承Writable接口)(对应上述问题2)。

RPC的实现流程

简单来说,Hadoop RPC = 动态代理 + 定制的二进制流。

远程的对象拥有固定的接口,这个接口用户也是可见的,只是真正的实现(Object)只在服务端。用户如果想使用哪个实现,调用过程是:

  • 先根据那个接口动态代理生成一个代理对象;
  • 调用这个代理对象;
  • 用户的请求被RPC捕捉到;
  • 然后包装成调用请求,序列化成数据流发送到服务端;
  • 服务端从数据流中解析出调用请求;
  • 然后根据用户所希望调用的接口;
  • 再把调用结果返回给客户端

RPC过程

接口:

  1. package com.ifcoding.proxy;
  2. public interface JieKou {
  3.     public int add(int a,int b);
  4.     public int sub(int a,int b);
  5. }

Object:

  1. package com.ifcoding.proxy;
  2. public class BeiDaiLiZhe implements JieKou {
  3.     @Override
  4.     public int add(int a, int b) {
  5.         return a+b;
  6.     }
  7.     @Override
  8.     public int sub(int a, int b) {
  9.         return a-b;
  10.     }
  11. }

Handler:

  1. package com.ifcoding.proxy;
  2. import java.lang.reflect.InvocationHandler;
  3. import java.lang.reflect.Method;
  4. public class DaiLiHandle implements InvocationHandler {
  5.     private Object beiDaiLiZheDuiXiang;
  6.     public DaiLiHandle(Object beiDaiLiZheDuiXiang) {
  7.         this.beiDaiLiZheDuiXiang = beiDaiLiZheDuiXiang;
  8.     }
  9.     @Override
  10.     public Object invoke(Object proxy, Method method, Object[] args)
  11.             throws Throwable {
  12.         System.out.println("before-----");
  13.         Object res = method.invoke(beiDaiLiZheDuiXiang, args);
  14.         System.out.println("after-----");
  15.         return res;
  16.     }
  17. }

测试:

  1. package com.ifcoding.proxy;
  2. import java.lang.reflect.Proxy;
  3. public class Test {
  4.     public static void main(String args[]){
  5.         BeiDaiLiZhe b = new BeiDaiLiZhe();
  6.         DaiLiHandle handle = new DaiLiHandle(b);
  7.         JieKou proxy = (JieKou)Proxy.newProxyInstance(b.getClass().getClassLoader(), b.getClass().getInterfaces(), handle);  //创建代理对象
  8.         System.out.println(proxy.add(12));
  9.     }
  10. }

上述只是简单一个利用动态代理和反射实现过程调用的例子。

RPC的实体模型

上面站在用户的角度,宏观地观察整个调用过程。这部分在细节上分析RPC都有哪些实体。为什么要提到实体?如果把RPC流程看作是流水线,这些实体就是一个个具体工作的工人,如果想深入了解流水线的处理,就要知道每个工人工作的职责及概况。

RPC在客户端的细节不多,需要注意的一点是:用户在调用代理对象时RPC是怎样拦截这次调用请求的。对动态代理清楚的都知道,创建代理对象时需要为它关联一个InvocationHandler,对代理对象的每次调用都会进入绑定的InvocationHandler中,RPC就从这里获取用户的请求。

RPC在服务端的模型由一系列实体组成,分别负责调用的整个流程。各个实体分工明确,各司其职。

  • Listener:监听RPC Server的端口,如果客户端有连接请求到达,它就接收连接,然后把连接转发到某个Reader,让Reader读取那个连接的数据。如果有多个Reader,当有新的连接过来时,就在这些Reader间顺序分发。
  • Reader:从某个客户端连接中读取数据流,把它转化成调用对象(call),然后就放到调用队列(call queue)里。
  • Handler:真正做事的实体。它从调用队列中获取调用信息,然后反射调用真正的对象,得到结果,再把此次调用放到相应队列(response queue)里。
  • Responder:不断地检查响应队列中是否有调用信息,如果有,就把调用的结果返回给客户端。

RPC Server

上图为RPC Server架构。

 

提示:整个调用流程中与网络有关的地方都是用NIO来处理的。

待续

后面将会基于RPC详细介绍一下文件在HDFS中的读取和写入。

1 条留言  访客:0 条  博主:0 条   引用: 1 条

来自外部的引用: 1 条

  • 从零学习Hadoop之文件在HDFS中的读取和写入 | If Coding

给我留言

*

Copyright © If Coding 保留所有权利.   Theme  Ality   

用户登录