一个极简版的RPC框架实现

RPC (remote Procedure Call) 远程过程调用,即通过某种协议,可以让不在同JVM中的应用进行通信,方
法调用。RPC进行通信一般都socket协议,传送的数据一般是需要经过特定进行进行编排/反编排处理,
调用双方必须都遵守此协议,即可进行通信交互。在java中提供socket协议和实现,编排也提供了序列
化机制,还需要使用到动态代理机制。

完整代码如下

 

package cn.seafood.admin;

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;
import java.util.concurrent.Executors;

public enum Rpc {
        //使用enum实现单例
        RPC;
        
        //暴露服务
        private java.util.concurrent.ExecutorService executorService = Executors.newCachedThreadPool();
        public void export(final Object service, final int port) {
                try {
                        final Socket request = new ServerSocket(port).accept();
                        executorService.submit(new Runnable() {
                                @Override
                                public void run() {
                                        try (final ObjectInputStream os = new ObjectInputStream(request.getInputStream());
                                                        final ObjectOutputStream oos = new ObjectOutputStream(request
                                                                        .getOutputStream());) {
                                                final String methodName = os.readUTF();
                                                // 参数
                                                final Object[] args = (Object[]) os.readObject();
                                                // 方法的参数类型
                                                final Class<?>[] paramTypes = (Class<?>[]) os.readObject();
                                                // 获取到方法对象
                                                final Method method = service.getClass().getMethod(methodName,
                                                                paramTypes);

                                                final Object result = method.invoke(service, args);
                                                oos.writeObject(result);
                                                request.close();  
                                        } catch (Exception e) {
                                                e.printStackTrace();
                                        }
                                }
                        });
                } catch (Exception e) {
                        e.printStackTrace();
                }
        }
        
        //引用服务
        @SuppressWarnings("unchecked")
        public <T> T ref(Class<T> interfaceClass, final String host, final int port) {
                        //使用动态代理拦截所有的方法
                return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[] { interfaceClass },
                                new InvocationHandler() {
                                        @Override
                                        //对接口方法的调用都会调到该方法上 
                                        public Object invoke(Object proxy, Method method, Object[] args)
                                                        throws Throwable {
                                                //进行socket调用
                                                try (final Socket socket = new Socket(host, port);
                                                                final ObjectOutputStream oos = new ObjectOutputStream(
                                                                                socket.getOutputStream());
                                                                final ObjectInputStream ois = new ObjectInputStream(
                                                                                socket.getInputStream());) {
                                                        //写入调用方法名
                                                        oos.writeUTF(method.getName());
                                                        //写入参数
                                                        oos.writeObject(args);
                                                          //写入参数类型
                                                        oos.writeObject(method.getParameterTypes());
                                                        final Object result = ois.readObject();
                                                        return result;
                                                } catch (Exception e) {
                                                        return e;
                                                }
                                        }
                                });
        }
        //测试
        public static void main(String[] args) {
//                 RPC.export(new HelloRpcImpl(), 9999);
                final HelloRpc ref = RPC.ref(HelloRpc.class, "127.0.0.1", 9999);
                final String hello = ref.hello("liuyi");
                System.out.println(hello); // hello liuyi
        }
}

interface HelloRpc {
        public String hello(String name);
}

class HelloRpcImpl implements HelloRpc {

        @Override
        public String hello(String name) {
                return "hello" + name;
        }
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值