Hadoop的RPC机制浅谈

 

 

Hadoop作为分布式计算框架,就必须涉及到RPCHadoop并没有使用JDK里提供的RPC技术,而是自己实现了一个RPC机制。

HadoopRPC逻辑可以划分为3部分

 

a、通信协议

b、服务器

c、客户端

 

结构图如下所示

 

 

1 通信协议

这里的通信协议不是指网络通信协议,而是指客户端/服务器端的通信接口。客户端需要和服务器端进行通信,不同的功能实现就需要不同的接口。VersionedProtocol是所有的通信协议的超类(接口),它本身只定义了一个方法。

 

2 服务器

服务器端通过socket监听客户端的请求,获取客户端需要调用的方法和参数之后,使用java反射机制来调用相对应的方法,并且将结果返回到客户端。

下面简单介绍服务端的几个关键类:

2.1 org.apache.hadoop.ipc.Server

这是个抽象类,它实现了对客户端的监听,请求处理框架,以及将结果返回给客户端,但具体处理由实现类来实现。

2.2 org.apache.hadoop.ipc.RPC.$Server

这个类是对org.apache.hadoop.ipc.Server的实现,主要是实现了对客户请求进行处理的方法。

 

服务器端启动的时候,会启动几个线程来响应客户端的请求。

1)   Listener线程

该线程负责监听客户端请求以及数据的接受,然后将接收到的数据组成一个Call实例,放到请求队列里面。

2)   Handler线程

该线程负责从请求队列中取出调用请求,通过调用抽象方法

public abstract Writable call(Class<?> protocol, Writable param, long receiveTime)来进行处理调用请求,并且将结果返回给客户端。

3)   Responder线程

响应数据由Handler线程返回给客户端,但如果有未写完的数据,则由Responder线程返回客户端。

 

3 客户端

 

HadoopRPC客户端代码其实就一个类:org.apache.hadoop.ipc.Client。这个类使用Java的动态代理技术,生成服务器的业务接口的代理,通过socket将调用的业务方法和参数传送到服务器端,并且等待服务器端的响应。

客户端调用的序列图如下:


 

1)     RPC客户端使用者首先调用RPCwaitForProxy方法,获取远程业务接口的动态代理,例如,DataNode中调用NameNode的时候,代码如下:

 
 

this.namenode = (DatanodeProtocol)

      RPC.waitForProxy(DatanodeProtocol.class,

                       DatanodeProtocol.versionID,

                       nameNodeAddr,

                       conf);

 
 

 

 

 

 

 

 

 

2)     RPC本身调用java的动态代理类Proxy来获取动态类,Proxy.newProxyInstance

 
 

VersionedProtocol proxy =

        (VersionedProtocol) Proxy.newProxyInstance(

            protocol.getClassLoader(), new Class[] { protocol },

            new Invoker(addr, ticket, conf, factory));

 
 

 

 

 

 

 

 

 

3)     获取动态类之后,接着调用业务方法。Invoker实现了InvocationHandler,所有的业务方法都是要通过

public Object invoke(Object proxy, Method method, Object[] args)来进行实际的调用。

 

 
 

ObjectWritable value = (ObjectWritable)

        client.call(new Invocation(method, args), address,

                    method.getDeclaringClass(), ticket);

 
 

 

 

 

 

   

4)     Client.call中将参数组装成一个Call实例,然后获取和服务器端的连接,将参数发送到服务器端,并且同步的等待服务器端返回结果。

Call call = new Call(param);

Connection connection = getConnection(addr, protocol, ticket, call);

connection.sendParam(call);

......

      while (!call.done) {

          call.wait();                           // wait for the result

       }

......

return call.value;

 
 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值