理解RPC底层实现原理

 涉及的知识点:动态代理,网络IO,序列化(RPC序列化框架,了解JDK序列化的缺点),反射,网络协议(通过哪种协议来传输数据),以下是RPC简单实现,可针对各个环节优化,比如IO可以采用NIO,序列化可以选择hessian。

客户端:

/**
 * 模拟客户端
 */
public class Client {

    public static void main(String[] args) throws IOException {
        UserService userService = new UserServiceImpl();
        UserService userServiceProxy = (UserService) ProxyDemo.getProxy(userService.getClass());
        User user = userServiceProxy.findUserById(123);
        System.out.println(user);
        StudentService studentService = new StudentServiceImpl();
        StudentService studentServiceProxy = (StudentService) ProxyDemo.getProxy(studentService.getClass());
        Student student = studentServiceProxy.findStudentByIdAndName(789,"lisi");
        System.out.println(student);
    }
}


/**
 * 动态代理,获取代理的对象
 */
public class ProxyDemo {

    public static Object getProxy(Class c){
        // 生成代理对象
        Object object = Proxy.newProxyInstance(c.getClassLoader(), c.getInterfaces(), new InvocationHandler(){
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // 1.与服务端建立连接,发送调用的服务相关信息
                Socket socket = new Socket("127.0.0.1",9999);
                // 发送数据到服务端
                System.out.println("发送数据到服务端");
                ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                // 服务名
                oos.writeUTF(c.getName());
                // 方法名
                oos.writeUTF(method.getName());
                // 方法参数类型
                oos.writeObject(method.getParameterTypes());
                // 方法参数
                oos.writeObject(args);
                oos.flush();
                // 2.接收服务端的信息
                System.out.println("接收服务端数据");
              /*  ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                Object o  = ois.readObject();*/
                // 自定义反序列化(Hessian也需要实现Serializable接口)
                HessianInput hi = new HessianInput(socket.getInputStream());
                Object o  = hi.readObject();
                oos.close();
                hi.close();
                socket.close();
                return o;
            }
        });
        return object;
    };

}

服务端:

/**
 * 模拟服务端
 */
public class Server {

    public static boolean isServerRunning = true;

    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        ServerSocket serverSocket = new ServerSocket(9999);
        while (isServerRunning){
            Socket s = serverSocket.accept();
            System.out.println("《《《开始处理客户端的请求》》》");
            process(s);
            s.close();
        }
        serverSocket.close();
    }

    /**
     *  处理任意接口,任意方法(包括重载),返回任意对象
     */
    private static void process(Socket s) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        // 1,接收客户端数据
        System.out.println("接收客户端数据");
        ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
        String className  =  ois.readUTF();
        String methodName = ois.readUTF();
        Class[] getParameterTypes = (Class[]) ois.readObject();
        Object[]  args = (Object[]) ois.readObject();
        // 2,返回数据给客户端
        /**
         * 可以通过Spring的注入获取到methodName的实例(一般服务暴露是URL的形式暴露的,
         * 这里就涉及服务端通过URL找到具体的执行方法,类似于SpringMVC的请求执行流程,
         * 具体看服务端怎么实现)
         */
        Object service = Class.forName(className).newInstance();
        Method method = service.getClass().getMethod(methodName,getParameterTypes);
        Object object = method.invoke(service,args);
        System.out.println("返回客户端数据");
       /* ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
        oos.writeObject(object);
        oos.flush();*/
        // 自定义序列化(Hessian也需要实现Serializable接口)
        OutputStream os = (OutputStream) s.getOutputStream();
        HessianOutput ho = new HessianOutput(os);
        ho.writeObject(object);
        ho.flush();
        ho.close();
    }

}

 

public class User implements Serializable {

    private String name;

    private int age;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

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

    public static void main(String[] args) {
        System.out.println(User.class.getName());
    }
}

public class UserServiceImpl  implements  UserService{
    @Override
    public User findUserById(int id) {
        return new User("demo",id);
    }

}

public class Student implements Serializable {

    private String name;

    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

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

}


public class StudentServiceImpl implements StudentService {
    @Override
    public Student findStudentByIdAndName(int id,String name) {
        return new Student(name,id);
    }
}

参考:

你的JavaBean是否真的需要实现Serializable

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值