从零手写RPC

作者: jijs | 来源:发表于2017-12-02 18:59 被阅读595次

    RPC概述

    RPC(Remote Proceduce Call 远程过程调用) 一般用来实现部署在不同机器上的系统之间的方法调用,使程序能够像访问本地系统资源一样,通过网络传输过去访问远端系统资源。

    RPC 调用过程

    1. Client 客户端调用方法实现,负责发起RPC调用。
    2. ClientStub/SereverStub 可以看作一个代理对象,屏蔽RPC调用过程中复杂的网络处理逻辑,使RPC透明化,使得调用远程方法想调用本地方法一样。
    3. Server 服务端提供远程服务。

    Stub 主要作用

    • 序列化:负责数据的序列化发序列化。
    • 网络传输:数据发送与接收。

    注:ServerStub又叫Skeleton。

    RPC 实现

    1. 远程服务接口

    public interface IHello {
        public String sayHello(String info);
    }
    

    2. 远程服务接口实现类(Server)

    public class HelloService implements IHello {
        public String sayHello(String info) {
            String result = "hello : " + info;
            System.out.println(result);
            return result;
        }
    }
    

    提供服务实现的类。

    3.服务器代理实现(Skeleton)

    public class RpcProxyServer {
        private IHello hello = new HelloService();
    
        public void publisherServer(int port) {
            try (ServerSocket ss = new ServerSocket(port)) {
                while (true) {
                    try (Socket socket = ss.accept()) {
                        try (ObjectInputStream ois = new ObjectInputStream(socket.getInputStream())) {
                            String method = ois.readUTF();
                            Object[] objs = (Object[]) ois.readObject();
                            Class<?>[] types = new Class[objs.length];
                            for (int i = 0; i < types.length; i++) {
                                types[i] = objs[i].getClass();
                            }
                            Method m = HelloService.class.getMethod(method, types);
                            Object obj = m.invoke(hello, objs);
    
                            try (ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream())) {
                                oos.writeObject(obj);
                                oos.flush();
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    1. 构建一个ServerSocket服务监听来自客户端的请求。
    2. 接收请求的数据。(方法名和参数)
    3. 根据请求的数据(方法名和参数),使用反射调用相应的服务。
    4. 输出服务的响应数据。

    4. RPC 客户端代理实现(ClientStub)

    public class RpcProxyClient<T> {
    
        public T proxyClient(Class<T> clazz) {
            return (T) clazz.cast(Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new InvocationHandler() {
    
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
                            try (Socket socket = new Socket("localhost", 8000)) {
                                try (ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream())) {
                                    oos.writeUTF(method.getName());
                                    oos.writeObject(args);
                                    oos.flush();
    
                                    try (ObjectInputStream ois = new ObjectInputStream(socket.getInputStream())) {
                                        return ois.readObject();
                                    }
                                }
                            }
                        }
                    }));
        }
    }
    
    1. 构建一个Socket,连接远程服务。
    2. 向远程服务发送数据。(方法名和方法参数)
    3. 接收远程服务响应的数据。

    5.服务端发布服务

    public class RpcServer {
        //发布服务
        public static void main(String[] args) {
            RpcProxyServer server = new RpcProxyServer();
            server.publisherServer(8000);
        }
    }
    

    6.客户端调用(Client)

    public class RpcClient {
        // 调用服务
        public static void main(String[] args) {
            RpcProxyClient<HelloService> rpcClient = new RpcProxyClient<>();
    
            IHello hello = rpcClient.proxyClient(HelloService.class);
            String s = hello.sayHello("dd");
            System.out.println(s);
        }
    }
    

    想了解更多精彩内容请关注我的公众号

    相关文章

      网友评论

        本文标题:从零手写RPC

        本文链接:https://www.haomeiwen.com/subject/lujapxtx.html