简单实现一个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框架包含很多东西,上面的代码可以逐步的扩展成一个还不错的框架。

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

时间: 2024-10-01 07:30:16

简单实现一个rpc框架的相关文章

简单Tomcat HTTP RPC框架

RPC基础知识 什么是RPC? RPC(Remote Procedure Call Protocol)--远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议. RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据.在OSI网络通信模型中,RPC跨越了传输层和应用层. RPC使得开发包括网络分布式多程序在内的应用程序更加容易. RPC的模型 C/S模式 基于传输层协议(例如TCP/IP)  远程调用不是新的一种数据传输协议事件响应

自己实现一个RPC框架

RPC简介 远程调用协议. 有多有用,多普遍就不摆了. 大概过程: 1. 调用客户端句柄,传输参数. 2. 封装参数等消息为网络传输格式传给远程主机 3. 服务器句柄得到消息并解析参数 4. 在服务器段执行要调用的代码,并把结果返回给服务器句柄 5. 服务器句柄封装返回结果并用网络传输给客户端 6. 客户端解析并进行其他处理 可见之问题主要有,通信方式.句柄实现.以及消息封装和解析(序列化及反序列化) RPC 之 通信 直接用Socket走TCP/IP 或者是UDP协议, 例如RMI 走HTTP

传智:自己简单实现一个struts2框架的demo

struts2的结构图: 代码实现: 组织结构: 主要代码: package cn.itcast.config; import org.apache.log4j.Logger; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import java.io.InputStream; import java.u

Java实现简单的RPC框架

一.RPC简介 RPC,全称为Remote Procedure Call,即远程过程调用,它是一个计算机通信协议.它允许像调用本地服务一样调用远程服务.它可以有不同的实现方式.如RMI(远程方法调用).Hessian.Http invoker等.另外,RPC是与语言无关的. RPC示意图 如上图所示,假设Computer1在调用sayHi()方法,对于Computer1而言调用sayHi()方法就像调用本地方法一样,调用 –>返回.但从后续调用可以看出Computer1调用的是Computer2

设计一个分布式RPC框架

0 前言 提前先祝大家春节快乐!好了,先简单聊聊. 我从事的是大数据开发相关的工作,主要负责的是大数据计算这块的内容.最近Hive集群跑任务总是会出现Thrift连接HS2相关问题,研究了解了下内部原理,突然来了兴趣,就想着自己也实现一个RPC框架,这样可以让自己在设计与实现RPC框架过程中,也能从中了解和解决一些问题,进而让自己能够更好的发展(哈哈,会不会说我有些剑走偏锋?不去解决问题,居然研究RPC.别急,这类问题已经解决了,后续我也会发文章详述的). 1 RPC流水线工程? 原理图上我已经

8.如何自己设计一个类似 Dubbo 的 RPC 框架?

作者:中华石杉 面试题 如何自己设计一个类似 Dubbo 的 RPC 框架? 面试官心理分析 说实话,就这问题,其实就跟问你如何自己设计一个 MQ 一样的道理,就考两个: 你有没有对某个 rpc 框架原理有非常深入的理解. 你能不能从整体上来思考一下,如何设计一个 rpc 框架,考考你的系统设计能力. 面试题剖析 其实问到你这问题,你起码不能认怂,因为是知识的扫盲,那我不可能给你深入讲解什么 kafka 源码剖析,dubbo 源码剖析,何况我就算讲了,你要真的消化理解和吸收,起码个把月以后了.

自行实现一个简易RPC框架

10分钟写一个RPC框架 1.RpcFramework package com.alibaba.study.rpc.framework; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; imp

微博轻量级RPC框架Motan正式开源:支撑千亿调用

支撑微博千亿调用的轻量级 RPC 框架 Motan 正式开源了,项目地址为https://github.com/weibocom/motan. 微博轻量级RPC框架Motan正式开源 Motan 是微博技术团队研发的基于 Java 的轻量级 RPC 框架,已在微博内部大规模应用多年,每天稳定支撑微博上亿次的内部调用.Motan 基于微博的高并发和高负载场景优化,成为一套简单.易用.高可用的 RPC 服务框架. Motan 功能特点:简单.易用.高可用 无侵入集成.简单易用,通过 Spring 配

Netty自娱自乐之类Dubbo RPC 框架设计构想 【上篇】

之前在前一篇的<Netty自娱自乐之协议栈设计>,菜鸟我已经自娱自乐了设计协议栈,gitHub地址为https://github.com/vOoT/ncustomer-protocal.先这一篇中,准备接着自娱去实现一个RPC框架,现在公司共的是Dubbo,那么先不看其代码,先自行实现一下吧. dubbo 包括 注册和服务调用,细节我们先不管,然后,我先先实现一个如下的简单模型 哈哈哈,第一个版本就是这么简单,粗暴.说到自定义配置,首先想到的是Spring 自定义标签,利用标签进行配置服务.而