Hadoop RPC Description

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 stream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(baos);
Writeable obj = new IntWriteable(1);
obj.write(out);
 
//byte stream to object
DataInputStream 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;
	}
	@Override
	public void readFields(DataInput in) throws IOException {
		value = in.readInt();
	}
	@Override
	public 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;
	}
	@Override
	public void readFields(DataInput in) throws IOException {
		int length = in.readInt();
		byte[] b = new byte[length];
		in.readFully(b);
		value = new String(b, "UTF-8");
	}
	@Override
	public 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;
	}
	@Override
	public void readFields(DataInput in) throws IOException {
		readObject(in, this);
	}
	@Override
	public 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();
	}
	@Override
	public 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();
		}
	}
	@Override
	public 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 {
	@Override
	public int sum(int x, int y) {
		return x + y;
	}
	@Override
	public 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 server
		Client 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 length
		int 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 full
			conn.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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值