模拟基本的RPC框架代码
来源:互联网 发布:osi网络模型 编辑:程序博客网 时间:2024/06/07 10:29
最近晚上没事,加上工作上要使用,所以开始自己学习RPC框架,目前写了一个基本的,便于理解,后续往里面添加内容。
**
服务提供方:
**
服务接口代码:
package zhm.rpc.server;public interface IServer { public String testMethod(String arg);}
接口实现类:
/** * rpcServerImpl.java * zhm.rpc.server * 2017年10月9日下午8:44:06 * */package zhm.rpc.server;/** * @author zhuheming * rpcServerImpl * 2017年10月9日下午8:44:06 */public class rpcServerImpl implements IServer { /* (non-Javadoc) * @see zhm.rpc.server.IServer#testMethod(java.lang.String) */ @Override public String testMethod(String arg) { // TODO Auto-generated method stub return "hello, "+arg; }}
反射类:
主要用于接收服务消费方发起的远程调用请求,得到method和args,就是方法和参数,再利用反射方式执行该方法,返回执行结果。
这里反射使用了commons.lang3包中的MethodUtils工具类实现。
/** * serverReflect.java * zhu.rpc.reflect * 2017年10月9日下午9:24:47 * */package zhu.rpc.reflect;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.net.ServerSocket;import java.net.Socket;import org.apache.commons.lang3.reflect.MethodUtils;/** * @author zhuheming * serverReflect * 2017年10月9日下午9:24:47 */public class ServerReflect implements Runnable{ private Object object; private int port; public ServerReflect(Object object,int port){ this.object=object; this.port=port; } /* (non-Javadoc) * @see java.lang.Runnable#run() */ @Override public void run() { // TODO Auto-generated method stub //新建连接 //SocketConnect sc=new SocketConnect(); //Socket socket=sc.connect("127.0.0.1", port); try { ServerSocket ss=new ServerSocket(port); while(true){ try { final Socket socket=ss.accept(); //建立输入 ObjectInputStream ois=new ObjectInputStream(socket.getInputStream()); try{ //得到方法名和参数列表 String method=ois.readUTF(); Object[] args=(Object[])ois.readObject(); System.out.print(method+" "+args.toString()); //反射得到对应方法的执行结果 Object resultObject=MethodUtils.invokeExactMethod(object, method, args); ObjectOutputStream oos=new ObjectOutputStream(socket.getOutputStream()); try{ //返回结果 oos.writeObject(resultObject); }catch(Exception e){ oos.writeObject(e); e.printStackTrace(); }finally{ oos.close(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ ois.close(); } }catch(Exception e){ e.printStackTrace(); } } } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } //private static Thread serverThread=new Thread(); //public void waittingServer(Class<T> serverClass,int port)}
测试入口:
省得麻烦,直接使用8081端口,用一个Thread来运行等待服务消费端的调用。
/** * test.java * zhm.rpc.test * 2017年10月9日下午10:18:33 * */package zhm.rpc.test;import zhm.rpc.server.IServer;import zhm.rpc.server.rpcServerImpl;import zhu.rpc.reflect.ServerReflect;/** * @author zhuheming * test * 2017年10月9日下午10:18:33 */public class testServer { public static void main(String args[]) throws InterruptedException{ IServer is=new rpcServerImpl(); Thread serverThread=new Thread(new ServerReflect(is,8081)); serverThread.start(); serverThread.join(); }}
**
服务消费方:
**
socket连接器,这里使用了一个连接接口IConnect,方便以后如果使用多种连接方式可以抽象
package zhm.rpc.connect;import java.net.Socket;/** * socket连接器 * @author zhuheming * socketConnet * 2017年9月28日下午11:29:24 */public class SocketConnect implements IConnect { @Override public Socket connect(String host, int port) { // TODO Auto-generated method stub //判断输入参数 if(!"".equalsIgnoreCase(host)&&port!=0){ Socket socket=null; try{ socket=new Socket(host,port); }catch(Exception e){ e.getStackTrace(); } return socket; }else{ return null; } } public void close(Object connectObject){ if(connectObject!=null){ try{ Socket socket=(Socket)connectObject; socket.close(); }catch(Exception e){ e.getStackTrace(); } } }}
服务消费方的动态代理实现:
思路是将服务提供方的IServer接口生成动态代理类,使用动态代理类执行执行IServer的接口方法时,会调用invoke方法,在invoke方法中,远程连接消费提供方,将方法名称和参数发送给服务提供方,由服务提供方返回执行结果。
/** * cosumeProxy.java * zhm.rpc.proxy * 2017年9月29日上午12:03:30 * */package zhm.rpc.proxy;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.Socket;import zhm.rpc.connect.SocketConnect;/** * @author zhuheming * cosumeProxy * 2017年9月29日上午12:03:30 */public class ConsumeProxy { //匿名内部类方法实现需要调用,所以host和port需要为final @SuppressWarnings("unchecked") public static <T> T consume(Class<T> interfaceClass,final String host,final int port){ //先建立一个InvocationHandler接口的对象(实现内部方法) //InvocationHandler invocationHandler=; return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[]{interfaceClass},new InvocationHandler(){ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{ //建立连接 SocketConnect sc=new SocketConnect(); Socket socket=sc.connect(host, port); //发送方法和参数 ObjectOutputStream ops=new ObjectOutputStream(socket.getOutputStream()); ops.writeUTF(method.getName()); ops.writeObject(args); //接收返回 ObjectInputStream ois=new ObjectInputStream(socket.getInputStream()); Object getObject=ois.readObject(); return getObject; } }); //return null; }}
服务提供方给的服务接口
注意,实现是在服务提供方,消费方只有接口
package zhm.rpc.server;public interface IServer { public String testMethod(String arg);}
服务消费方入口:
先生成代理类,再远程执行方法。
package zhm.rpc.test;import zhm.rpc.proxy.ConsumeProxy;import zhm.rpc.server.IServer;public class Test { //远程调用服务端的testMethod方法,客户端只有接口,没有方法实现。 public static void main(String args[]) throws InterruptedException{ Object obj= ConsumeProxy.consume(IServer.class, "127.0.0.1", 8081); if(obj!=null){ System.out.println(obj.getClass().getInterfaces().toString()); //System.out.println(obj.toString()); System.out.println("not null!"); }else{ System.out.println("null!"); } IServer rpc=(IServer)obj; for(int i=0;i<100;i++){ System.out.println(rpc.testMethod(""+i)); Thread.sleep(1000); } }}
好了,以上就是最简单的RPC远程执行框架,要想丰满起来,后续还要考虑很多,如自己实现序列化反序列化,软负载均衡,高可用NIO通讯方式,服务的解耦合IOC方式,以及服务治理,类似zk的服务发布等。
继续努力吧。
阅读全文
0 0
- 模拟基本的RPC框架代码
- 一起写RPC框架(九)RPC服务提供端一--服务端的基本代码结构
- Hadoop RPC基本框架
- 一起写RPC框架(十五)RPC注册中心二--注册中心的基本实现
- 一起写RPC框架(二十四)RPC测试篇一---基本业务逻辑的测试
- RPC框架的实现
- RPC框架性能基本比较测试
- RPC框架性能基本比较测试
- RPC框架性能基本比较测试
- RPC框架性能基本比较测试
- RPC框架性能基本比较测试
- RPC框架性能基本比较测试
- RPC框架性能基本比较测试
- RPC框架性能基本比较测试
- RPC框架性能基本比较测试
- Akka编写一个RPC框架,模拟多个Worker连接Master的情况的案例
- XML-RPC的基本描述
- 几行代码实现RPC框架
- [线性代数]矩阵
- 心情复杂
- hdu1828 Picture(线段树+扫描线+矩形周长并)
- hdu-3016-Man Down(线段树)
- android6.0及以上获取wifi mac地址的方法(亲测可行)
- 模拟基本的RPC框架代码
- LeetCode刷题(8)
- 机器学习中的L0L1L2
- 去除inline-block元素间间距的几种方法
- 单例设计模式
- python学习第二天-操作列表
- HDU 1556 Color the ball【树状数组||前缀和】
- 将字符串转换为基本数据类型
- unity_NGUI系统学习(十六)_给控件对象添加可拖拽的功能和可调节大小的功能