码迷,mamicode.com
首页 > 其他好文 > 详细

简单实现一个rpc框架

时间:2015-08-31 01:19:08      阅读:286      评论:0      收藏:0      [点我收藏+]

标签:框架   zk   rpc   

与其说框架不如讲是个小demo,废话不多说直接上代码

package com.tang.rpc;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 实现一个简单的RpcServer 例子: HelloService为自定义的服务
 * 
 * <pre>
 * {
 * 	@code
 * 	// 先导出服务以供远端的客户端调用
 * 	public class ServiceProvider {
 * 		public static void main(String[] args) {
 * 			HelloService service = new HelloServiceImpl();
 * 			try {
 * 				RpcServer.exportService(service);
 * 			} catch (IOException e) {
 * 				e.printStackTrace();
 * 			}
 * 		}
 * 
 * 	}
 * }
 * </pre>
 * 
 * <pre>
 * {
 * 	@code
 * 	// 引用用远程发布的服务
 * 	public class ServiceConsumer {
 * 		public static void main(String[] args) {
 * 			try {
 * 				// 返回的是服务的一个代理
 * 				HelloService service = RpcServer.referService(HelloService.class, "127.0.0.1");
 * 				String message = service.sayHello("lili");
 * 				System.out.println(message);
 * 			} catch (Exception e) {
 * 				e.printStackTrace();
 * 			}
 * 		}
 * 	}
 * }
 * </pre>
 *
 * 该类实现的是一个简单的PpcServer,在此基础上可以进行以下的扩展
 * 线程池处理调用请求、通信层不使用BIO使用NIO甚至是NIO框架(Netty,Mina等)
 * 使用序列化框架比如protostuff、避免反射调用损耗性能使用动态代理生成代理类、增加 注册中心可以使用zk来完成......
 *
 */
public class RpcServer {
	// 服务端端口
	public static int port = 9999;

	/**
	 * 导出服务,需要做的是打开服务端口解析请求,并调用相应的方法,并返回结果
	 * 
	 * @throws IOException
	 */
	public static void exportService(final Object service) throws IOException {
		if (null == service) {
			throw new IllegalArgumentException("service is null");
		}
		System.out.println("Export service " + service + "on port " + port);

		@SuppressWarnings("resource")
		ServerSocket serverSocket = new ServerSocket(port);
		for (;;) {
			try {
				final Socket socket = serverSocket.accept();
				// 一请求一线程处理
				new Thread(new Runnable() {
					public void run() {
						try {
							ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
							// 方法名
							String methodName = in.readUTF();

							Object result = null;
							try {
								result = invoke(service, in, methodName);
								ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
								try {
									out.writeObject(result);
									out.flush();
								} catch (Exception e) {
									e.printStackTrace();
								} finally {
									out.close();
								}
							} catch (Exception e1) {
								e1.printStackTrace();
							} finally {
								in.close();
							}
						} catch (IOException e) {
							e.printStackTrace();
						} finally {
							if (null != socket) {
								try {
									socket.close();
								} catch (IOException e) {
									e.printStackTrace();
								}
							}
						}
					}

					// 解析参数并反射调用返回调用结果
					private Object invoke(final Object service, ObjectInputStream in, String methodName)
							throws Exception {
						Object result = null;
						// 参数类型
						Class<?>[] parameterTypes = (Class<?>[]) in.readObject();
						// 参数值
						Object[] args = (Object[]) in.readObject();
						try {
							// 反射获取方法名
							Method method = service.getClass().getMethod(methodName, parameterTypes);
							if (null == method) {
								throw new NoSuchMethodException();
							}
							// 反射调用
							result = method.invoke(service, args);
							// 回写结果
						} catch (Throwable t) {
							t.printStackTrace();
							result = t;
						}
						return result;
					}

				}).start();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 引入服务
	 */
	@SuppressWarnings("unchecked")
	public static <T> T referService(final Class<T> service, final String host) throws Exception {
		if (null == service) {
			throw new IllegalArgumentException("service is null");
		}
		System.out.println("refer service " + service);

		return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
				new InvocationHandler() {

					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						Socket socket = new Socket(host, port);
						try {
							ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
							try {
								out.writeUTF(method.getName());
								out.writeObject(method.getParameterTypes());
								out.writeObject(args);
								ObjectInputStream in = new ObjectInputStream(socket.getInputStream());

								try {
									Object result = in.readObject();
									if (result instanceof Throwable) {
										throw (Throwable) result;
									}
									return result;
								} finally {
									in.close();
								}
							} finally {
								out.close();
							}
						} finally {
							socket.close();
						}
					}
				});
	}
}
一个RPC框架包含很多东西,上面的代码可以逐步的扩展成一个还不错的框架。

版权声明:本文为博主原创文章,未经博主允许不得转载。

简单实现一个rpc框架

标签:框架   zk   rpc   

原文地址:http://blog.csdn.net/tangyongzhe/article/details/48111835

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!