RPC远程过程调用

RPC介绍

RPC的全称是Remote Procedure Call,即远程过程调用,实现方式有很多,如RMI,WebService等。
RPC的实现包括两方,一方称作服务端(server),一方称作客户端(client)。客户端发送RPC请求到服务端,服务端通过客户端提供的参数执行对应的请求方法,将执行结果返回给客户端,一次RPC调用结束。

基于TCP协议实现的RPC

基于Java的Socket API,我们能够实现一个简单的RPC调用,具体示例如下:包括服务端接口及接口的实现,客户端接口以及远程调用。

代码实现结构图

基于TCP协议实现的RPC的结构图

客户端和服务端接口HelloService

package cn.xiaoyu.rpc.service;

public interface HelloService {
    public String sayHello(String name);
}

服务端接口的实现HelloServiceImpl

package cn.xiaoyu.rpc.service;

public class HelloServiceImpl implements HelloService{
    @Override
    public String sayHello(String name) {
        return "Hello " + name;
    }
}

服务端主程序MainServer

package cn.xiaoyu.rpc.main;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;

import cn.xiaoyu.rpc.service.HelloServiceImpl;

public class MainServer {
    public static void main(String[] args) throws Exception {
        //将服务接口的示例先初始化,这儿应该还有更好的方法来实现!
        HashMap<String, Object> map = new HashMap<>();
        map.put("cn.xiaoyu.rpc.service.HelloService",new HelloServiceImpl());

        ServerSocket server = new ServerSocket(1234);

        while(true){
            Socket socket = server.accept();

            // 读取传递过来的信息
            ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());
            String interfacename = inputStream.readUTF(); // 接口名称
            String methodName = inputStream.readUTF(); // 方法名称
            Class<?>[] parameterTypes = (Class<?>[]) inputStream.readObject(); // 参数类型
            Object[] params = (Object[]) inputStream.readObject();

            // 执行调用过程
            Class clazz = Class.forName(interfacename); //获取接口的class
            Object service = map.get(interfacename); //获取接口的实现对象
            Method method = clazz.getMethod(methodName, parameterTypes); //获取需要的调用的方法
            Object result = method.invoke(service, params); 

            // 将执行结果输出到客户端
            ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());
            outputStream.writeObject(result);

        }
    }
}

客户端主程序MainClient

package cn.xiaoyu.rpc.main;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.Socket;

import cn.xiaoyu.rpc.service.HelloService;

public class MainClient {
    public static void main(String[] args) throws Exception{
        // 接口名稱
        String interfacename = HelloService.class.getName();
        // 需要遠程執行的方法
        Method method = HelloService.class.getMethod("sayHello",String.class);
        //需要传递参数
        Object[] params = {"bubu"};

        Socket socket = new Socket("127.0.0.1",1234);

        //将方法名称和参数传递到服务端
        ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());
        outputStream.writeUTF(interfacename); //调用的接口名称
        outputStream.writeUTF(method.getName()); //调用的方法的名称
        outputStream.writeObject(method.getParameterTypes());
        outputStream.writeObject(params);

        //从服务端读取方法的执行结果
        ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());
        Object result = inputStream.readObject();

        System.out.println(result);
    }
}

#