Hadoop RPC Description

来源:互联网 发布:基德新秀数据 编辑:程序博客网 时间:2024/06/03 16:22

Serialization

Object to byte stream and byte stream to Object

package com.talend.example.rpc;import java.io.DataInput;import java.io.DataOutput;import java.io.IOException;interface Writeable {void readFields(DataInput in) throws IOException;void write(DataOutput out) throws IOException;}

Serialization action

//object to byte streamByteArrayOutputStream baos = new ByteArrayOutputStream();DataOutputStream out = new DataOutputStream(baos);Writeable obj = new IntWriteable(1);obj.write(out); //byte stream to objectDataInputStream in = new DataInputStream(socket.getInputStream());Writeable obj = new StringWriteable();obj.readFields(in );

A IntWriteable

package com.talend.example.rpc;import java.io.DataInput;import java.io.DataOutput;import java.io.IOException;public class IntWriteable implements Writeable {int value;public int getValue() {return value;}public void setValue(int value) {this.value = value;}public IntWriteable() {}public IntWriteable(int value) {this.value = value;}@Overridepublic void readFields(DataInput in) throws IOException {value = in.readInt();}@Overridepublic void write(DataOutput out) throws IOException {out.writeInt(value);}}

A StringWriteable

package com.talend.example.rpc;import java.io.DataInput;import java.io.DataOutput;import java.io.IOException;public class StringWriteable implements Writeable {String value;public String getValue() {return value;}public void setValue(String value) {this.value = value;}public StringWriteable() {}public StringWriteable(String value) {this.value = value;}@Overridepublic void readFields(DataInput in) throws IOException {int length = in.readInt();byte[] b = new byte[length];in.readFully(b);value = new String(b, "UTF-8");}@Overridepublic void write(DataOutput out) throws IOException {byte[] b = value.getBytes("UTF-8");out.writeInt(b.length);out.write(b);}public static void writeString(DataOutput out, String content)throws IOException {byte[] b = content.getBytes("UTF-8");out.writeInt(b.length);out.write(b);}public static String readString(DataInput in) throws IOException {int length = in.readInt();byte[] b = new byte[length];in.readFully(b);return new String(b, "UTF-8");}}

A special Writeable : ObjectWriteable

package com.talend.example.rpc;import java.io.DataInput;import java.io.DataOutput;import java.io.IOException;import java.lang.reflect.Array;import java.util.HashMap;import java.util.Map;public class ObjectWriteable implements Writeable {private static final Map<String, Class<?>> PRIMITIVE_NAMES = new HashMap<String, Class<?>>();static {PRIMITIVE_NAMES.put("boolean", Boolean.TYPE);PRIMITIVE_NAMES.put("byte", Byte.TYPE);PRIMITIVE_NAMES.put("char", Character.TYPE);PRIMITIVE_NAMES.put("short", Short.TYPE);PRIMITIVE_NAMES.put("int", Integer.TYPE);PRIMITIVE_NAMES.put("long", Long.TYPE);PRIMITIVE_NAMES.put("float", Float.TYPE);PRIMITIVE_NAMES.put("double", Double.TYPE);PRIMITIVE_NAMES.put("void", Void.TYPE);}Object instance;Class declaredClass;public ObjectWriteable() {}public ObjectWriteable(Object instance, Class declaredClass) {this.instance = instance;this.declaredClass = declaredClass;}public Object getInstance() {return instance;}public void setInstance(Object instance) {this.instance = instance;}public Class getDeclaredClass() {return declaredClass;}public void setDeclaredClass(Class declaredClass) {this.declaredClass = declaredClass;}@Overridepublic void readFields(DataInput in) throws IOException {readObject(in, this);}@Overridepublic void write(DataOutput out) throws IOException {writeObject(out, instance, declaredClass);}public static Object readObject(DataInput in, ObjectWriteable objectWritable)throws IOException {String className = StringWriteable.readString(in);Class<?> declaredClass = PRIMITIVE_NAMES.get(className);if (declaredClass == null) {try {declaredClass = Class.forName(className);} catch (ClassNotFoundException e) {throw new RuntimeException("readObject can't find class "+ className, e);}}Object instance;if (declaredClass.isPrimitive()) {if (declaredClass == Boolean.TYPE) {instance = Boolean.valueOf(in.readBoolean());} else if (declaredClass == Character.TYPE) {instance = Character.valueOf(in.readChar());} else if (declaredClass == Byte.TYPE) {instance = Byte.valueOf(in.readByte());} else if (declaredClass == Short.TYPE) {instance = Short.valueOf(in.readShort());} else if (declaredClass == Integer.TYPE) {instance = Integer.valueOf(in.readInt());} else if (declaredClass == Long.TYPE) {instance = Long.valueOf(in.readLong());} else if (declaredClass == Float.TYPE) {instance = Float.valueOf(in.readFloat());} else if (declaredClass == Double.TYPE) {instance = Double.valueOf(in.readDouble());} else if (declaredClass == Void.TYPE) {instance = null;} else {throw new IllegalArgumentException("Not a primitive: "+ declaredClass);}} else if (declaredClass.isArray()) {int length = in.readInt();instance = Array.newInstance(declaredClass.getComponentType(),length);for (int i = 0; i < length; i++) {Array.set(instance, i, readObject(in, null));}} else if (declaredClass == String.class) {instance = StringWriteable.readString(in);} else {Class instanceClass = null;String str = "";try {str = StringWriteable.readString(in);instanceClass = Class.forName(str);} catch (ClassNotFoundException e) {throw new RuntimeException("readObject can't find class " + str, e);}Writeable writable = null;try {writable = (Writeable) instanceClass.newInstance();} catch (Exception e) {}writable.readFields(in);instance = writable;}if (objectWritable != null) {objectWritable.declaredClass = declaredClass;objectWritable.instance = instance;}return instance;}public static void writeObject(DataOutput out, Object instance,Class declaredClass) throws IOException {StringWriteable.writeString(out, declaredClass.getName());if (declaredClass.isArray()) {int length = Array.getLength(instance);out.writeInt(length);for (int i = 0; i < length; i++) {writeObject(out, Array.get(instance, i),declaredClass.getComponentType());}} else if (declaredClass == String.class) {StringWriteable.writeString(out, (String) instance);} else if (declaredClass.isPrimitive()) {if (declaredClass == Boolean.TYPE) {out.writeBoolean(((Boolean) instance).booleanValue());} else if (declaredClass == Character.TYPE) {out.writeChar(((Character) instance).charValue());} else if (declaredClass == Byte.TYPE) {out.writeByte(((Byte) instance).byteValue());} else if (declaredClass == Short.TYPE) {out.writeShort(((Short) instance).shortValue());} else if (declaredClass == Integer.TYPE) {out.writeInt(((Integer) instance).intValue());} else if (declaredClass == Long.TYPE) {out.writeLong(((Long) instance).longValue());} else if (declaredClass == Float.TYPE) {out.writeFloat(((Float) instance).floatValue());} else if (declaredClass == Double.TYPE) {out.writeDouble(((Double) instance).doubleValue());} else if (declaredClass == Void.TYPE) {} else {throw new IllegalArgumentException("Not a primitive: "+ declaredClass);}} else if (Writeable.class.isAssignableFrom(declaredClass)) {StringWriteable.writeString(out, instance.getClass().getName());((Writeable) instance).write(out);} else {throw new IOException("Can't write: " + instance + " as "+ declaredClass);}}}


Send and receive procedure information by the net

Method information Writeable

package com.talend.example.rpc;import java.io.DataInput;import java.io.DataOutput;import java.io.IOException;import java.lang.reflect.Method;public class MethodInformation implements Writeable {public String getMethod() {return method;}public void setMethod(String method) {this.method = method;}public Object[] getParameters() {return parameters;}public void setParameters(Object[] parameters) {this.parameters = parameters;}public Class[] getParameterClazz() {return parameterClazz;}public void setParameterClazz(Class[] parameterClazz) {this.parameterClazz = parameterClazz;}String method;Class[] parameterClazz;Object[] parameters;public MethodInformation() {}public MethodInformation(Method method, Object[] parameters) {this.method = method.getName();this.parameters = parameters;this.parameterClazz = method.getParameterTypes();}@Overridepublic void readFields(DataInput in) throws IOException {method = StringWriteable.readString(in);parameters = new Object[in.readInt()];parameterClazz = new Class[parameters.length];ObjectWriteable objectWritable = new ObjectWriteable();for (int i = 0; i < parameters.length; i++) {parameters[i] = ObjectWriteable.readObject(in, objectWritable);parameterClazz[i] = objectWritable.getDeclaredClass();}}@Overridepublic void write(DataOutput out) throws IOException {StringWriteable.writeString(out, method);out.writeInt(parameterClazz.length);for (int i = 0; i < parameterClazz.length; i++) {ObjectWriteable.writeObject(out, parameters[i], parameterClazz[i]);}}}

A protocol

package com.talend.example.rpc;public interface Protocol {}
A sum protocol
package com.talend.example.rpc;interface SumProtocol extends Protocol {int sum(int x,int y);IntWriteable sum(IntWriteable x, IntWriteable y);}

A sum protocol implement

package com.talend.example.rpc;public class SumProtocolImple implements SumProtocol {@Overridepublic int sum(int x, int y) {return x + y;}@Overridepublic IntWriteable sum(IntWriteable x, IntWriteable y) {int value = x.getValue() + y.getValue();IntWriteable result = new IntWriteable(value);return result;}}
RPC client that use java dynamic proxy
package com.talend.example.rpc;import java.io.IOException;import java.lang.reflect.Proxy;import java.net.InetSocketAddress;import java.nio.ByteBuffer;public class RPC {static ByteBuffer HEADER = ByteBuffer.wrap("wrpc".getBytes());public static Protocol getProxy(Class<? extends Protocol> protocol,InetSocketAddress addr) throws IOException {final Invoker invoker = new Invoker(protocol, addr);Protocol proxy = (Protocol) Proxy.newProxyInstance(protocol.getClassLoader(), new Class[] { protocol }, invoker);return proxy;}}

invoker for dynamic proxy and send the request,receive the response

package com.talend.example.rpc;import java.io.IOException;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.net.InetSocketAddress;public class Invoker implements InvocationHandler {Class<? extends Protocol> protocol;InetSocketAddress address;Invoker(Class<? extends Protocol> protocol, InetSocketAddress address)throws IOException {this.protocol = protocol;this.address = address;}public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {MethodInformation mi = new MethodInformation(method, args);// send it from client to serverClient client = new Client(address);ObjectWriteable result = (ObjectWriteable) client.call(protocol,mi);return result.getInstance();}}
RPC internal client
package com.talend.example.rpc;import java.io.ByteArrayOutputStream;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.net.InetSocketAddress;import java.net.Socket;import javax.net.SocketFactory;public class Client {Socket socket;public Client(InetSocketAddress address) throws IOException {socket = SocketFactory.getDefault().createSocket();socket.connect(address);}ObjectWriteable call(Class<? extends Protocol> protocol, Writeable method)throws IOException {ByteArrayOutputStream baos = new ByteArrayOutputStream();DataOutputStream dos = new DataOutputStream(baos);StringWriteable.writeString(dos, protocol.getName());method.write(dos);byte[] data = baos.toByteArray();int length = data.length;DataOutputStream out = new DataOutputStream(socket.getOutputStream());out.write(RPC.HEADER.array());out.writeInt(length);out.write(data);out.flush();DataInputStream in = new DataInputStream(socket.getInputStream());ObjectWriteable obj = new ObjectWriteable();ObjectWriteable.readObject(in, obj);socket.close();return obj;}}
RPC server
package com.talend.example.rpc;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.lang.reflect.Method;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.util.Iterator;import com.sun.corba.se.impl.oa.poa.ActiveObjectMap.Key;public class Server {ServerSocketChannel ssc;Selector selector = null;int port;Object protocolInstance = null;Server(int port, Object protocolInstance) {this.port = port;this.protocolInstance = protocolInstance;}void init() throws IOException {ssc = ServerSocketChannel.open();ssc.configureBlocking(false);ssc.socket().bind(new InetSocketAddress(port));selector = Selector.open();ssc.register(selector, SelectionKey.OP_ACCEPT);}void listen() throws IOException {while (true) {selector.select();Iterator<SelectionKey> itera = selector.selectedKeys().iterator();while (itera.hasNext()) {SelectionKey key = null;try {key = itera.next();itera.remove();if (!key.isValid()) {continue;}if (key.isAcceptable()) {doAccept(key);} else if (key.isReadable()) {doRead(key);} else if (key.isWritable()) {doWrite(key);}} catch (Exception e) {//TODO} finally {}}}}private void doAccept(SelectionKey key) throws IOException {ServerSocketChannel server = (ServerSocketChannel) key.channel();SocketChannel channel;while ((channel = server.accept()) != null) {channel.configureBlocking(false);SelectionKey skey = channel.register(selector, SelectionKey.OP_READ| SelectionKey.OP_WRITE);Connection conn = new Connection(channel);skey.attach(conn);}}private void doWrite(SelectionKey key) throws IOException {SocketChannel channel = (SocketChannel) key.channel();Connection conn = (Connection) key.attachment();if (!conn.result.hasRemaining()) {}if (conn.resultIsReady) {channel.write(conn.result);}}private void doRead(SelectionKey key) throws IOException {SocketChannel channel = (SocketChannel) key.channel();Connection conn = (Connection) key.attachment();// read rpc header or data lengthint count = -1;if (conn.rpcheaderbuffer.hasRemaining()) {count = channel.read(conn.rpcheaderbuffer);if (count < 0 || conn.rpcheaderbuffer.hasRemaining()) {return;}}if (!conn.hasReadRPCHeader) {// now header buffer is fullconn.rpcheaderbuffer.flip();if (!conn.rpcheaderbuffer.equals(RPC.HEADER)) {System.out.println("is not a rpc request");key.cancel();channel.close();}conn.hasReadRPCHeader = true;conn.rpcheaderbuffer.clear();return;}if (conn.databuffer == null) {conn.rpcheaderbuffer.flip();int dataLength = conn.rpcheaderbuffer.getInt();conn.databuffer = ByteBuffer.allocate(dataLength);}channel.read(conn.databuffer);if (!conn.databuffer.hasRemaining()) {conn.databuffer.flip();conn.process(conn.databuffer.array());}}class Connection {MethodInformation mi = new MethodInformation();ByteBuffer rpcheaderbuffer = ByteBuffer.allocate(4);ByteBuffer databuffer;ByteBuffer result;boolean hasReadRPCHeader = false;boolean resultIsReady = false;SocketChannel channel;public Connection(SocketChannel channel) {this.channel = channel;}void process(byte[] data) throws IOException {ByteArrayInputStream bais = new ByteArrayInputStream(data);DataInputStream in = new DataInputStream(bais);String protocol = StringWriteable.readString(in);try {Class protocolClass = Class.forName(protocol);mi.readFields(in);String method = mi.getMethod();Class[] paraClasses = mi.getParameterClazz();Object[] parameters = mi.getParameters();Method met = protocolClass.getMethod(method, paraClasses);Object result = met.invoke(protocolInstance, parameters);doResponse(result, met.getReturnType());} catch (Exception e) {e.printStackTrace();}}private void doResponse(Object result, Class resulttype)throws IOException {ByteArrayOutputStream baos = new ByteArrayOutputStream();DataOutputStream dos = new DataOutputStream(baos);ObjectWriteable.writeObject(dos, result, resulttype);this.result = ByteBuffer.wrap(baos.toByteArray());resultIsReady = true;}}public static void main(String[] args) throws IOException {Server server = new Server(9000, new SumProtocolImple());server.init();server.listen();}}

start RPC server

Server server = new Server(9000, new SumProtocolImple());server.init(); server.listen();
A RPC client example :
package com.talend.example.rpc;import java.io.IOException;import java.net.InetSocketAddress;public class AppClient {public static void main(String[] args) throws IOException {SumProtocol sumprotocol = (SumProtocol) (RPC.getProxy(SumProtocol.class, new InetSocketAddress("127.0.0.1", 9000)));int result = sumprotocol.sum(2, 4);System.out.println(result);IntWriteable result2 = sumprotocol.sum(new IntWriteable(4), new IntWriteable(4));System.out.println(result2.getValue());}}
0 0
原创粉丝点击