Hadoop源码之RPC机制
来源:互联网 发布:手机服务器软件 编辑:程序博客网 时间:2024/05/16 03:34
研读Hadoop源码,不得不说其中的RPC机制。
实现RPC的几个基本步骤:
1)客户端需要有一个负责与远程服务端对象通信的对象,称为A;
2)服务端需要有一个负责与远程客户端对象通信的对象,称为B;
3)A负责将客户端请求的Java类型方法、参数,序列化成字节流,通过网络传递给B;
4)B负责将通过网络收到的请求字节流,反序列化成Java类型方法、参数,传递给真正的服务端对象,并调用方法;
5)B收到服务端对象返回的结果,再序列化传递给A;
6)A反序列化后,将结果返回给客户端调用者。
如果采用RMI实现上述RPC过程的话,A即为存根对象,B即为骨架对象;实际上CORBA架构也离不开上述的过程。
下面从RPC调用过程的先后出场顺序,阐述hadoop的RPC方案:
1、客户端使用Java 反射,获取远程服务端对象的代理对象,可以视为A,同时解决了类型安全的问题;
public static Object getProxy(Class protocol, InetSocketAddress addr, Configuration conf) { return Proxy.newProxyInstance(protocol.getClassLoader(), new Class[] { protocol }, new Invoker(addr, conf)); }
通过new 一个Invoker,来实现invocationHandler,实现调用过程,具体调用又是通过New一个Client对象的call方法实现;
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { ObjectWritable value = (ObjectWritable) CLIENT.call(new Invocation(method, args), address); return value.get(); }
2、上述的call调用与后续的调用,都是通过实现Writable接口的对象与ObjectWritable对象,来实现序列化与反序列化的,其中还包括所有Java基本类型在内都实现了Writable接口;
public interface Writable { void write(DataOutput out) throws IOException; //序列化接口 void readFields(DataInput in) throws IOException; //反序列化接口}
3、CLIENT在向服务端发送请求时,进行了同步,解决了线程安全的问题,并通过新建一个connection线程将调用序列化输出;
public Writable call(Writable param, InetSocketAddress address) throws IOException { Connection connection = getConnection(address); //新启一个connection线程 Call call = new Call(param); //封装成call synchronized (call) { connection.sendParam(call); // connection线程发送请求 //以下省略 }
connection线程中,对call对象进行序列化输出;
public void sendParam(Call call) throws IOException {calls.put(new Integer(call.id), call);synchronized (out) { if (LOG.isLoggable(Level.FINE)) LOG.fine(getName() + " sending #" + call.id); try { writingCall = call; out.writeInt(call.id); call.param.write(out); //参数序列化,并写出 out.flush(); } finally { writingCall = null; }}
4、服务端socket监听线程监听到请求时,会开启一个connection线程,构造参数对象,进行反序列化,构造call对象,唤醒call队列;
while (running) { int id; try { id = in.readInt(); // try to read an id } catch (SocketTimeoutException e) { continue; } if (LOG.isLoggable(Level.FINE)) LOG.fine(getName() + " got #" + id); Writable param = makeParam(); // 构造参数对象 param.readFields(in); // 反序列化 Call call = new Call(id, param, this); // 构造call对象 synchronized (callQueue) { callQueue.addLast(call); // queue the call callQueue.notify(); // 唤醒call队列 }
5、服务端Handler线程被唤醒后,调用服务端对象,获取结果后,又序列化输出;
Writable value = null; try { value = call(call.param); // 调用 } catch (IOException e) { LOG.log(Level.INFO, getName() + " call error: " + e, e); error = getStackTrace(e); } catch (Exception e) { LOG.log(Level.INFO, getName() + " call error: " + e, e); error = getStackTrace(e); } DataOutputStream out = call.connection.out; synchronized (out) { out.writeInt(call.id); // write call id out.writeBoolean(error!=null); // write error flag if (error != null) value = new UTF8(error); value.write(out); // write value out.flush(); }
调用过程如下:
public Writable call(Writable param) throws IOException { Invocation call = (Invocation)param; if (verbose) log("Call: " + call); Method method = implementation.getMethod(call.getMethodName(), call.getParameterClasses()); Object value = method.invoke(instance, call.getParameters()); //真正调用服务端对象 if (verbose) log("Return: "+value); return new ObjectWritable(method.getReturnType(), value); }
6、以DataNode客户端为例,DataXceiveServer线程监听到服务端返回的数据后,就新开启一个DataXceiver线程,DataXceiver将返回的数据进行反序列化后再进行相应处理;
if (op == OP_WRITE_BLOCK) { // // Read in the header // DataOutputStream reply = new DataOutputStream(new BufferedOutputStream(s.getOutputStream())); try { boolean shouldReportBlock = in.readBoolean(); Block b = new Block(); b.readFields(in); //反序列化
这样就完成了一个完整的RPC调用过程。
- Hadoop源码之RPC机制
- Hadoop DFS源码研究之---Hadoop RPC机制
- Hadoop RPC机制+源码分析
- Hadoop源码分析之二(RPC机制之Call处理)
- Hadoop源码分析之二(RPC机制之Call处理)
- Hadoop源码分析之一(RPC机制之Server)
- Hadoop源码分析之一(RPC机制之Server)
- Hadoop基础之RPC机制以及HDFS源码分析
- Hadoop源码分析之一(RPC机制之Server)
- hadoop的RPC机制源码分析
- Hadoop RPC源码分析之Client
- Hadoop RPC源码分析之Server
- Hadoop源码解析之RPC协议
- hadoop源码解析之RPC分析
- 源码级强力分析Hadoop的RPC机制
- 源码级强力分析hadoop的RPC机制
- 源码级强力分析hadoop的RPC机制
- 源码级强力分析hadoop的RPC机制
- Linq 检测DbDataReader 对象中是否有特定名字的列存在
- 解决oracle initialization or shutdown in progress问题----oracle
- Java多线程(八)之Semaphore、CountDownLatch、CyclicBarrier、Exchanger
- php画椭圆
- C#、最简单、事件委托、订阅事件、订阅者模式
- Hadoop源码之RPC机制
- Java中abstract和interface的区别
- Ubuntu下设置mysql用于远程访问
- 关于tomcat版本的选择
- 解决popupwindow中弹出输入法被遮挡问题
- linux文件查找与文件管理
- UVC摄像头移植总结
- 常用的JavaScript验证正则表达式
- Codeforces Round #155 (Div. 2)