徒手打造 - RPC远程通讯框架v1

手写RPC框架V1

gitee地址:https://gitee.com/kylin1991_admin/rpc_handwriting

Api.jar

1、写一个IHelloService接口,类似dubbo
public interface IHelloService {
   String sayHello(String context);
 }
2、一个RpcRequest请求模型
@Data
public class RpcRequest implements Serializable {
    private String className;
    private String methodName;
    private Object[] parameters;
}

Server

1、Server 服务注册
  public class Server {
      public static void main(String[] args) {
          IHelloService helloService = new IHelloServiceImpl();
          RpcProxyServer rpcProxyServer = new RpcProxyServer(helloService,8080);
          rpcProxyServer.publisher();
      }
  }
2、RpcProxyServer 服务发布
public class RpcProxyServer {
    private Object service;
    private int port;

    public RpcProxyServer(Object service, int port) {
        this.service = service;
        this.port = port;
    }

    public void publisher() {
        try {
            ServerSocket serverSocket = new ServerSocket(port);
            while (true) {
                Socket socket = serverSocket.accept();
                executor.execute(new ProcessorHandler(service,socket));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static final Executor executor = new ThreadPoolExecutor(
            Runtime.getRuntime().availableProcessors(),
            Runtime.getRuntime().availableProcessors(),
            60L,
            TimeUnit.MINUTES,
            new ArrayBlockingQueue<>(Runtime.getRuntime().availableProcessors()),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy()
    );
}
3、请求处理ProcessorHandler
public class ProcessorHandler implements Runnable {
    private Object service;
    private Socket socket;

    public ProcessorHandler(Object service, Socket socket) {
        this.service = service;
        this.socket = socket;
    }

    @Override
    public void run() {
        try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
             ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream())) {

            // 接受请求
            RpcRequest rpcRequest = (RpcRequest) objectInputStream.readObject();

            // 反射调用并且返回结果
            objectOutputStream.writeObject(invoke(rpcRequest));
            objectOutputStream.flush();


        } catch (IOException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
            e.printStackTrace();
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private Object invoke(RpcRequest rpcRequest, Object service) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class clazz = Class.forName(rpcRequest.getClassName());
        Class<?>[] parametersTypes = new Class<?>[rpcRequest.getParameters().length];
        for (int i = 0; i < parametersTypes.length; i++) {
            parametersTypes[i] = rpcRequest.getParameters()[i].getClass();
        }
        Method method = clazz.getMethod(rpcRequest.getMethodName(), parametersTypes);
        return method.invoke(service, rpcRequest.getParameters());
    }
}

Client

1、Client 发起请求
public class Client {
    public static void main(String[] args) {
        RpcProxyClient rpcProxyClient = new RpcProxyClient();
        IHelloService helloService = rpcProxyClient.proxyClient(IHelloService.class,"localhost",8080);
        System.out.println(helloService.sayHello("lilei"));;
    }
}
2、远程调用(采用jdk动态代理)
  • RpcProxyClient
public class RpcProxyClient {
    public <T> T proxyClient(Class<?> interfacesCls, String host, int port) {
        return (T) Proxy.newProxyInstance(
                interfacesCls.getClassLoader(),
                new Class<?>[]{interfacesCls},
                new RemoteInvocationHandler(host,port));
    }
}
  • RemoteInvocationHandler 用于远程方法调用
public class RemoteInvocationHandler implements InvocationHandler {
    private String host;
    private int port;

    public RemoteInvocationHandler(String host, int port) {
        this.host = host;
        this.port = port;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //包装请求
        RpcRequest rpcRequest = new RpcRequest();
        rpcRequest.setClassName(method.getDeclaringClass().getName());
        rpcRequest.setMethodName(method.getName());
        rpcRequest.setParameters(args);

        //发送请求,并且获得结果
        RpcNetTransport rpcNetTransport = new RpcNetTransport(host, port);
        return rpcNetTransport.send(rpcRequest);
    }
}
3、RpcNetTransport 调用
public class RpcNetTransport {
    private String host;
    private int port;

    public RpcNetTransport(String host, int port) {
        this.host = host;
        this.port = port;
    }

    public Object send(RpcRequest rpcRequest) {
        Object result = null;
        try (Socket socket = new Socket(host, port);
             ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
             ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream())) {

            objectOutputStream.writeObject(rpcRequest);
            objectOutputStream.flush();

            result = objectInputStream.readObject();

        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        return result;
    }
}

测试

1、启动Server

2、启动Client

测试成功!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章