• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
gaohuan30
博客园    首页    新随笔    联系   管理    订阅  订阅
模拟RPC-演变过程

记录学习RPC逐步演变

一、rpc-01

  1.基础准备

 

public interface IUserService {
    User getUserById (int id);
}

  

@Data
public class User implements Serializable {
    private int id;
    private String name;

    public User(int id) {
    }

    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

  2.模拟服务端

/**
 * 模拟服务端
 */
public class Server {
private static boolean running = true;
    public static void main(String[] args) throws  Exception{
        ServerSocket serverSocket = new ServerSocket(8888);
        while (running){
            Socket s = serverSocket.accept();
            System.out.println("服务端监听提示:"+s.getLocalSocketAddress().toString());
            System.out.println(s.getInetAddress().toString());
            System.out.println(s.getLocalAddress().toString());
            System.out.println("客户端请求地址:"+s.getRemoteSocketAddress().toString());
            System.out.println("我是清晰分明的分界线");
            System.out.println();
            process(s);
            s.close();
        }
        serverSocket.close();
    }

    private static void process(Socket s) throws  Exception {
        // 拿到输入流
        InputStream inputStream = s.getInputStream();
        OutputStream outputStream = s.getOutputStream();
        // 组建数据输入流对象
        DataInputStream dataInputStream = new DataInputStream(inputStream);
        DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
        // 拿到请求数据
        int id = dataInputStream.readInt();
        IUserService userService = new UserServiceImpl();
        User user = userService.getUserById(id);
        // 输出数据
        dataOutputStream.writeInt(user.getId());
        dataOutputStream.writeUTF(user.getName());
        // 刷新
        dataOutputStream.flush();

        dataOutputStream.close();
        dataInputStream.close();
        outputStream.close();
        inputStream.close();

    }
}

  3.客户端调用

/**
 * 模仿请求端
 */
public class Client {
    public static void main(String[] args) throws Exception {
        Socket s = new Socket("127.0.1.1",8888);
        // 创建字节数组输出流
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        // 创建数据输出流包装
        DataOutputStream dataOutputStream = new DataOutputStream(bout);
        // 写入请求值
        dataOutputStream.writeInt(1);
        s.getOutputStream().write(bout.toByteArray());
        s.getOutputStream().flush();

        // 读取 创建数据输入流
        DataInputStream dataInputStream = new DataInputStream(s.getInputStream());
        int id = dataInputStream.readInt();
        String name = dataInputStream.readUTF();
        User user = new User(id, name);
        System.out.println("请求返回数据-"+user);
        dataInputStream.close();
        dataOutputStream.close();
        bout.close();
        s.close();
    }
}

  4.结果

服务端监听提示:/127.0.1.1:8888
/127.0.0.1
/127.0.1.1
客户端请求地址:/127.0.0.1:55967
我是清晰分明的分界线

服务端监听提示:/127.0.1.1:8888
/127.0.0.1
/127.0.1.1
客户端请求地址:/127.0.0.1:56024
我是清晰分明的分界线



**************
请求返回数据-User{id=1, name='rpc_name'}

  客户端+服务的 写死代码,比较臃肿

二、rpc-02

  客户端代码隐藏io细节 ,使用Stud 帮助我们处理io

  1.服务端

public class Server {
    private static boolean flag = true;
    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(8888);
        while (flag){
            Socket s = serverSocket.accept();
            process(s);
            s.close();
        }
        serverSocket.close();
    }

    /**
     * 处理信息,返回数据
     * @param s
     * @throws IOException
     */
    private static void process(Socket s) throws IOException {
        DataInputStream dataInputStream = new DataInputStream(s.getInputStream());
        int id = dataInputStream.readInt();
        DataOutputStream dataOutputStream = new DataOutputStream(s.getOutputStream());
        dataOutputStream.writeInt(id);
        dataOutputStream.writeUTF(id+"-"+new Random().nextInt(20));
        dataOutputStream.flush();
        dataOutputStream.close();
        dataInputStream.close();
    }
}

 

  2.客户端

public class Client {
    public static void main(String[] args) throws  Exception{
        Stub stub = new Stub();
        User userById = stub.findUserById(500000);
        System.out.println(userById);
    }
}
public class Stub {
    public User findUserById(Integer id) throws  Exception{
        Socket socket = new Socket("127.0.0.1",8888);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream);
        dataOutputStream.writeInt(id);
        socket.getOutputStream().write(byteArrayOutputStream.toByteArray());
        socket.getOutputStream().flush();
        DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
        int id2 = dataInputStream.readInt();
        String name = dataInputStream.readUTF();
        User u = new User(id2,name);
        dataInputStream.close();
        dataOutputStream.close();
        byteArrayOutputStream.close();
        socket.close();
        return u;
    }
}

 三、rpc-03

  调用端使用了JDK动态代理模式,代理客户端调用的接口,以便使用服务的提供好的接口类

   1.client

public class Client {
    public static void main(String[] args) {
        IUserService sub = Stub.getSub();
        User userById = sub.getUserById(1111);
        System.out.println(userById);
    }
}
public class Stub {
    public static IUserService getSub(){
        InvocationHandler invocationHandler = new InvocationHandler() {
        // 此处o是代理生成的对象类似com.sun.proxy.$Proxy0 method 要执行的方法, objests 传递的参数 @Override public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
          System.out.println(Arrays.toString(o.getClass().getInterfaces())); Socket socket = new Socket("127.0.0.1",8888); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream); dataOutputStream.writeInt(11111); socket.getOutputStream().write(byteArrayOutputStream.toByteArray()); socket.getOutputStream().flush(); DataInputStream dataInputStream = new DataInputStream(socket.getInputStream()); int id = dataInputStream.readInt(); String name = dataInputStream.readUTF(); User user = new User(id,name); dataInputStream.close(); dataOutputStream.close(); byteArrayOutputStream.close(); socket.close(); return user; } }; try { // Class[] c = new Class[]{IUserService.class}; // Class<?>[] interfaces = IUserService.class.getInterfaces(); Object o = Proxy.newProxyInstance(IUserService.class.getClassLoader(), new Class[]{IUserService.class}, invocationHandler); return (IUserService) o; }catch (Exception e){ e.printStackTrace(); } return null; } }

 四·rpc-04

  使用动态传递方法,服务端接收具体数据进行具体方法处理

   1.客户端

public class Client {
    public static void main(String[] args) {
        IUserService sub = Stub.getStub();
        User userById = sub.getUserById(22222);
        System.out.println(userById);
        IUserService sub2 = Stub.getStub();
        User userById2 = sub2.getUserById(111);
        System.out.println(userById2);

    }
}
public class Stub {
    public static IUserService getStub(){
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                Socket socket = new Socket("127.0.0.1",8888);
                System.out.println(o.getClass().getName());
                ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
                // 传递方法名
                objectOutputStream.writeUTF(method.getName());
                //传递方法参数类型
                objectOutputStream.writeObject(method.getParameterTypes());
                //传递方法参数
                objectOutputStream.writeObject(objects);
                objectOutputStream.flush();
                DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
                int id = dataInputStream.readInt();
                String name = dataInputStream.readUTF();
                User user = new User(id,name);
                dataInputStream.close();
                objectOutputStream.close();
                socket.close();
                return user;
            }
        };
        try {
            Object o = Proxy.newProxyInstance(IUserService.class.getClassLoader(), new Class[]{IUserService.class}, invocationHandler);
            return (IUserService) o;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}

  2.服务端

public class Server {
    private static boolean flag = true;
    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(8888);
        while (flag){
            Socket s = serverSocket.accept();
            process(s);
            s.close();
        }
        serverSocket.close();
    }

    /**
     * 处理信息,返回数据
     * @param s
     * @throws IOException
     */
    private static void process(Socket s) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        ObjectInputStream objectInputStream = new ObjectInputStream(s.getInputStream());
        // 传递过来的方法名称
        String methodName = objectInputStream.readUTF();
        // 传递过来的参数类型
        Class[] parameterType = (Class[]) objectInputStream.readObject();
        // 传递的参数数据
        Object[] args = (Object[]) objectInputStream.readObject();
        IUserService userService = new UserServiceImpl();
        // 使用参数类型+参数+方法名 执行具体方法
        Method method = userService.getClass().getMethod(methodName,parameterType);
        User user = (User) method.invoke(userService, args);

        DataOutputStream dataOutputStream = new DataOutputStream(s.getOutputStream());
        dataOutputStream.writeInt(user.getId());
        dataOutputStream.writeUTF(user.getName());
        dataOutputStream.flush();
        dataOutputStream.close();
        objectInputStream.close();
    }
}

 五·rpc-05

  支持单个接口的多方法

1.客户端

public class Client {
    public static void main(String[] args) {
        IUserService sub = Stub.getStub();
        User userById = sub.getUserById(22222);
        System.out.println(userById);
        sub.run();

    }
} 
public class Stub {
    public static IUserService getStub(){
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                Socket socket = new Socket("127.0.0.1",8888);
                System.out.println(o.getClass().getName());
                ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
                // 传递方法名
                objectOutputStream.writeUTF(method.getName());
                //传递方法参数类型
                objectOutputStream.writeObject(method.getParameterTypes());
                //传递方法参数
                objectOutputStream.writeObject(objects);
                objectOutputStream.flush();
                ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
                User user = (User) objectInputStream.readObject();
                objectInputStream.close();
                objectOutputStream.close();
                socket.close();
                return user;
            }
        };
        try {
            Object o = Proxy.newProxyInstance(IUserService.class.getClassLoader(), new Class[]{IUserService.class}, invocationHandler);
            return (IUserService) o;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}

  2.服务端

public class Server {
    private static boolean flag = true;
    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(8888);
        while (flag){
            Socket s = serverSocket.accept();
            process(s);
            s.close();
        }
        serverSocket.close();
    }

    /**
     * 处理信息,返回数据
     * @param s
     * @throws IOException
     */
    private static void process(Socket s) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        ObjectInputStream objectInputStream = new ObjectInputStream(s.getInputStream());
        // 传递过来的方法名称
        String methodName = objectInputStream.readUTF();
        // 传递过来的参数类型
        Class[] parameterType = (Class[]) objectInputStream.readObject();
        // 传递的参数数据
        Object[] args = (Object[]) objectInputStream.readObject();
        IUserService userService = new UserServiceImpl();
        // 使用参数类型+参数+方法名 执行具体方法
        Method method = userService.getClass().getMethod(methodName,parameterType);
        User user = (User) method.invoke(userService, args);

        ObjectOutputStream objectOutputStream = new ObjectOutputStream(s.getOutputStream());
        objectOutputStream.writeObject(user);
        objectOutputStream.flush();
        objectInputStream.close();
    }
}

  六·rpc-06

  传递接口名称

  1.添加公用

@Data
public class Student implements Serializable {
    private Integer id;
    private String studentName;

    public Student() {
    }

    public Student(Integer id, String studentName) {
        this.id = id;
        this.studentName = studentName;
    }

}  
public interface IStudentService {
    Student getStudentById(Integer id);
}
public class StudentServiceImpl implements IStudentService {
    @Override
    public Student getStudentById(Integer id) {
        return new Student(id,"student_name");
    }
}

  2.客户端

public class Client {
    public static void main(String[] args) {
        IUserService sub = (IUserService)Stub.getStub(IUserService.class);
        User userById = sub.getUserById(22222);
        System.out.println(userById);
        sub.run();
        System.out.println("-----------------");
        IStudentService stub = (IStudentService) Stub.getStub(IStudentService.class);
        Student studentById = stub.getStudentById(789);
        System.out.println(studentById);
    }
}
public class Stub {
    public static Object getStub(Class clazz){
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                Socket socket = new Socket("127.0.0.1",8888);
                System.out.println(clazz.getName());
                ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
                // 传递调用类名称
                objectOutputStream.writeUTF(clazz.getName());
                // 传递方法名
                objectOutputStream.writeUTF(method.getName());
                //传递方法参数类型
                objectOutputStream.writeObject(method.getParameterTypes());
                //传递方法参数
                objectOutputStream.writeObject(objects);
                objectOutputStream.flush();
                ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
                Object o1 = objectInputStream.readObject();
                objectInputStream.close();
                objectOutputStream.close();
                socket.close();
                return o1;
            }
        };
        try {
            Object o = Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, invocationHandler);
            return o;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}

  3.服务端

public class Server {
    private static boolean flag = true;
    private static Map<String, Class>  mapClazz = Maps.newHashMap();
    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(8888);
        mapClazz.put("com.example.common.IUserService",UserServiceImpl.class);
        mapClazz.put("com.example.common.IStudentService", StudentServiceImpl.class);
        while (flag){
            Socket s = serverSocket.accept();
            process(s);
            s.close();
        }
        serverSocket.close();
    }

    /**
     * 处理信息,返回数据
     * @param s
     * @throws IOException
     */
    private static void process(Socket s) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        ObjectInputStream objectInputStream = new ObjectInputStream(s.getInputStream());
        // 传递过来的类名称
        String clazzName = objectInputStream.readUTF();
        // 传递过来的方法名称
        String methodName = objectInputStream.readUTF();
        // 传递过来的参数类型
        Class[] parameterType = (Class[]) objectInputStream.readObject();
        // 传递的参数数据
        Object[] args = (Object[]) objectInputStream.readObject();
        Class clazz = null;
        // 从服务端注册表找到相应的具体类
//        clazz = UserServiceImpl.class;
        clazz  =  mapClazz.get(clazzName);
        // 使用参数类型+参数+方法名 执行具体方法
        Method method = clazz.getMethod(methodName, parameterType);
        Object o = (Object) method.invoke(clazz.newInstance(), args);

        ObjectOutputStream objectOutputStream = new ObjectOutputStream(s.getOutputStream());
        objectOutputStream.writeObject(o);
        objectOutputStream.flush();
        objectInputStream.close();
    }
}

  七·使用Hessian替代JDK自带序列化

/**
 *          <dependency>
 *             <groupId>com.caucho</groupId>
 *             <artifactId>hessian</artifactId>
 *             <version>4.0.60</version>
 *         </dependency>
 */
public class HesianTest {
    public static void main(String[] args) throws Exception {
        User user = new User(1, "name");
        byte[] serialize = serialize(user);
        System.out.println(serialize.length);
        byte[] serialize2 = serializeJDK(user);
        System.out.println(serialize2.length);
        User user1 = (User)deserialize(serialize);
        System.out.println(user1);
    }

    /**
     * 使用Hessian 反序列化
     * @param serialize
     * @return
     * @throws Exception
     */
    private static Object deserialize(byte[] serialize) throws Exception{
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(serialize);
        Hessian2Input hessian2Input = new Hessian2Input(byteArrayInputStream);
        Object o = hessian2Input.readObject();
        hessian2Input.close();
        byteArrayInputStream.close();
        return o ;
    }

    /**
     * 使用Hessian 序列化
     * @param user
     * @return
     * @throws Exception
     */
    private static byte[] serialize(User user) throws Exception {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        Hessian2Output hessian2Output = new Hessian2Output(byteArrayOutputStream);
        hessian2Output.writeObject(user);
        hessian2Output.flush();

        byte[] bytes = byteArrayOutputStream.toByteArray();
        hessian2Output.close();
        byteArrayOutputStream.close();
        return bytes;
    }
    /**
     * 使用jdk 序列化
     * @param user
     * @return
     * @throws Exception
     */
    private static byte[] serializeJDK(User user) throws Exception {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(user);
        objectOutputStream.flush();

        byte[] bytes = byteArrayOutputStream.toByteArray();
        objectOutputStream.close();
        byteArrayOutputStream.close();
        return bytes;
    }
}

  

posted on 2020-04-11 22:32  gaohuan30  阅读(225)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3