Hadoop RPC 源码阅读3

来源:互联网 发布:大数据maven 教程 编辑:程序博客网 时间:2024/05/16 09:17

DataNode要向NameNode发送请求,希望得到一个应答,Datanode是通过调用RPC类的getProxy方法在本地创建一个Namenode的代理,getProxy使用动态代理机制来创建一个指定服务端的代理。

下面分析ipc.RPC源码



ipc.RPC源码分析:


RPC中有一些内部类,除了前面提到的RPC.Server中之外,还有Invocation、ClientCache、Invoker等。

下面先看RPC的getProxy()方法:

  /** Construct a client-side proxy object that implements the named protocol,   * talking to a server at the named address. */  public static VersionedProtocol getProxy(      Class<? extends VersionedProtocol> protocol,      long clientVersion, InetSocketAddress addr, UserGroupInformation ticket,      Configuration conf, SocketFactory factory, int rpcTimeout) throws IOException {    if (UserGroupInformation.isSecurityEnabled()) {      SaslRpcServer.init(conf);    }    VersionedProtocol proxy =                                 // 通过Invoker类来 获取一个代理实例        (VersionedProtocol) Proxy.newProxyInstance(            protocol.getClassLoader(), new Class[] { protocol },            new Invoker(protocol, addr, ticket, conf, factory, rpcTimeout));      long serverVersion = proxy.getProtocolVersion(protocol.getName(),                                                   clientVersion);    if (serverVersion == clientVersion) {      return proxy;    } else {      throw new VersionMismatch(protocol.getName(), clientVersion,                                 serverVersion);    }  }

RPC的内部类Invoker类的继承自InvocationHandler,下面看一下Invoker.invoker()方法:

    public Object invoke(Object proxy, Method method, Object[] args)      throws Throwable {      final boolean logDebug = LOG.isDebugEnabled();      long startTime = 0;      if (logDebug) {        startTime = System.currentTimeMillis();      }      ObjectWritable value = (ObjectWritable)        client.call(new Invocation(method, args), remoteId); // 将方法名和参数封装为一个Invocation对象传给client对象的call方法,获得服务器的返回结果值      if (logDebug) {                                     // 这里,client的call会对这些请求参数做处理,发给服务器端,具体分析见前文ipc.Client的源码分析。        long callTime = System.currentTimeMillis() - startTime;        LOG.debug("Call: " + method.getName() + " " + callTime);      }      return value.get();    }







以下是Hadoop RPC机制的一个剪影。




客户端调用NameNode的方法,就要获取NameNode的实例对象。
这样客户端首先调用RPC类中的getProxy方法,getProxy返回NameNode实例。
在getProxy中,首先RPC会生成一个Data对象data,给data设置方法名,函数名,
将当前的data传给Client,Client会与Server通信,获取一个完整的data。
与此同时,server端会调用RPC的getServer方法,要求启动Server实例,
Server实例启动后,收到Client发来的data,然后Server获取一个NameNode实例,
并将NameNode实例和data实例传递给Handler类,Handler通过反射机制设置Data,
Server与Client通信,将包含NameNode完整信息的实例data传给Client,由此getProxy方法获得NameNode实例
客户端获取NameNode实例,调用NameNode方法。

package Test;import NameNode.NameNode;import RPC.RPC;public class TestRpcClient {public static void main(String[] args) {for (int i = 0; i < 10; i++) {  new Thread(new Runnable() {                @Override                public void run() {                    try {                        NameNode nameNode = RPC.getProxy(NameNode.class, "127.0.0.1", 8888);                        System.out.println(nameNode.doSomething1("我想做个代理!"));                    } catch (Exception e) {                    }                }            }).start();}}}
package RPC;import java.io.IOException;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.net.InetAddress;import java.net.ServerSocket;import java.net.Socket;import java.net.UnknownHostException;import server.Server;import Client.Client;import Data.Data;import NameNode.NameNode;public class RPC {//start a serverpublic static void getServer(NameNode nn, String host, int backlog, int port) throws UnknownHostException, IOException {ServerSocket ss = new  ServerSocket(port, backlog, InetAddress.getByName(host));while (true) {Socket s = ss.accept();new Server(nn, s).start();}}//start a client connecting to the given serverpublic static NameNode getProxy(Class clazz, String host, int port) { Class[] interfaces = new Class[1];     interfaces[0] = clazz;     return  (NameNode) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), interfaces, new InvocationHandler() {            @Override            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                Data data = new Data();                data.setMethodName((String) method.getName());                data.setParaName((String) args[0]);                return Client.processClient(data, "127.0.0.1", 8888).getReturnValue();            }        });}}

package Client;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.net.Socket;import java.net.UnknownHostException;import Data.Data;public class Client {public static Data processClient(Data data, String host, int port) throws UnknownHostException, IOException, ClassNotFoundException {    Socket socket = new Socket(host,port);           //send a message to a given server    ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());        objectOutputStream.writeObject(data);        objectOutputStream.flush();                //get message from server        ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());        data = (Data) objectInputStream.readObject();                //close connection        objectOutputStream.close();        objectInputStream.close();                return data;}}
package Data;import java.io.Serializable;public class Data implements Serializable{public String getMethodName() {return methodName;}public void setMethodName(String methodName) {this.methodName = methodName;}public String getParaName() {return paraName;}public void setParaName(String paraName) {this.paraName = paraName;}public String getReturnValue() {return returnValue;}public void setReturnValue(String returnValue) {this.returnValue = returnValue;}private String methodName;private String paraName;private String returnValue;}

package Test;import NameNode.NameNodeImp;import RPC.RPC;public class TestRpcServer { public static void main(String[] args) throws Exception{        RPC.getServer(new NameNodeImp(),  "127.0.0.1", 200,8888);    }}


package server;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.net.ServerSocket;import java.net.Socket;import Data.Data;import NameNode.NameNode;import NameNode.NameNodeImp;public class Server extends Thread{private NameNode nn;private Socket socket; public Server(NameNode nn, Socket ss) {this.nn = nn;this.socket = ss;}public void run() {ObjectInputStream objectInputStream = null;try {objectInputStream = new ObjectInputStream(socket.getInputStream());Data data = (Data) objectInputStream.readObject();try {data = Handler.doMethod(nn, data);ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());            objectOutputStream.writeObject(data);            objectOutputStream.flush();            objectOutputStream.close();            objectInputStream.close();} catch (NoSuchMethodException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SecurityException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}}// apply java reflex private static class Handler {public static Data doMethod(NameNode nn, Data data) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {String methodName = data.getMethodName(); System.out.println(methodName);Class clazz = nn.getClass();Method m = clazz.getMethod(methodName, String.class);String result = (String) m.invoke(nn, data.getParaName());data.setReturnValue(result);return data;}}}

package NameNode;public interface NameNode {public String doSomething(String message) ;public String doSomething1(String message);}

package NameNode;public class NameNodeImp implements NameNode{@Overridepublic String doSomething(String message) {// TODO Auto-generated method stubreturn message+"Hello";}@Overridepublic String doSomething1(String message) {// TODO Auto-generated method stubreturn message+ "Hello2";}}



0 0