首页 > 其他分享 >230103_50_RPC底层原理

230103_50_RPC底层原理

时间:2023-01-03 23:34:31浏览次数:45  
标签:230103 bill 50 Stub RPC IUserService new import com

  • client通过调用stub来屏蔽网络通信的细节,这样就不用再client中写网络发送和接收的代码实现
package com.bill.rpc02;

import com.bill.rpc.common.User;

import java.io.IOException;

/**
 * @Auther: wangchunwen
 * @Date: 2023/1/2 - 01 - 02 - 22:42
 * @Description: com.bill.rpc02
 * @version: 1.0
 */
public class Client {
    public static void main(String[] args) throws IOException {
        Stub stub = new Stub();
        System.out.println(stub.findUser(123).toString());
    }
}

  • Stub进行网络代理,只能代理一个方法findUser,如果这个接口增加一个方法,则需要重新修改Stub,需要进一步进行优化。
package com.bill.rpc03;

import com.bill.rpc.common.IUserService;

/**
 * @Auther: wangchunwen
 * @Date: 2023/1/3 - 01 - 03 - 22:43
 * @Description: com.bill.rpc03
 * @version: 1.0
 */
public class Client {
    public static void main(String[] args) {
        IUserService service = Stub.getStub();
        System.out.println(service.findUser(123));
    }
}
  • client:实现一个代理,这个代理可以提供一个类。这个类实现了IUserService接口,自然而然就实现了这个接口的所有方法,这样通过创建的这个类,就可以调用这个类里面的方法,同时实现这个方法的时候也帮忙屏蔽了网络通信层面的东西,实现原理:当我调用findUser方法的时候,这个代理帮我添加了一些网络服务的代码,帮我实现网络通信功能。本质上这个是通过设计模式中动态代理模式实现的。
  • 如何通过代理创建这个类?
    • 如果通过自己实现一个类来实现类的创建,那么如果新增接口后则需要再写一个类,比较麻烦;
    • 考虑是否可以通过动态生成一个类,动态产生一个新的类;
    • 动态代理是rpc的核心之一;
  • Stub实现
package com.bill.rpc03;

import com.bill.rpc.common.IUserService;
import com.bill.rpc.common.User;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.Socket;

/**
 * @Auther: wangchunwen
 * @Date: 2023/1/3 - 01 - 03 - 22:44
 * @Description: com.bill.rpc03
 * @version: 1.0
 */
public class Stub {
    public static IUserService getStub(){
        InvocationHandler h = new InvocationHandler() {
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // 写出去
                Socket s = new Socket("127.0.0.1",8888);
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                DataOutputStream dos = new DataOutputStream(baos);
                dos.writeInt(123);

                s.getOutputStream().write(baos.toByteArray());
                s.getOutputStream().flush();

                // 读进来
                DataInputStream dis = new DataInputStream(s.getInputStream());
                int id = dis.readInt();
                String name = dis.readUTF();
                User user = new User(id,name);

                System.out.println(user);

                dos.close();
                s.close();
                return user;
            }
        };
        Object o = Proxy.newProxyInstance(IUserService.class.getClassLoader(),new Class[] {IUserService.class},h);
        System.out.println(o.getClass().getName());
        System.out.println(o.getClass().getInterfaces()[0]);
        return (IUserService)o;
    }
}
  • Stub说明
    • InvocationHandler是一个处理器,用来处理调用;
    • 当调用findUser方法是,实际上是调用处理器中invoke方法,invoke方法中三个参数
      • 参数1:谁在调用这个方法?
      • 参数2:调用的是哪个方法?
      • 参数3:调用的传入的参数是什么?
    • 通过动态代理创建这个类,创建动态代理通过Proxy.newProxyInstance创建,三个参数
      • 参数1:要实现接口的classloader,表明要创建哪个接口的实现类
      • 参数2:要实现接口的class,表明要创建哪个接口的实现类
      • 参数3:使用的是哪个处理器,这个处理器可以将哪些代码塞进来

标签:230103,bill,50,Stub,RPC,IUserService,new,import,com
From: https://www.cnblogs.com/wcwblog/p/17023700.html

相关文章