您的位置:首页 > 运维架构

Hadoop的RPC机制浅谈

2011-06-17 00:59 232 查看
 

 

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

Hadoop的RPC逻辑可以划分为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
客户端

 

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

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



 

1)    
RPC客户端使用者首先调用RPC的waitForProxy方法,获取远程业务接口的动态代理,例如,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[] {

9d05
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;

 
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息