使用Socket实现一个简单的RPC

使用Socket实现一个简单的RPC

实现原理

consumer端使用jdk动态代理,代理要调用的接口建立socket连接,传入socket连接ip和端口号。

代理类发送socket连接,把封装的参数数据(需要类名、方法名、参数类型反射构建方法 执行咱们需要调用的方法)输出到socket中。

provider端接收接收(accept)socket消息,通过接收到的封装参数构建执行方法并写入socket返回。

具体实现

待调用接口类

public interface OrderApi {

    String getOrderName(String name);
}

传输rpc参数

@Getter
@Setter
public class RpcRequest implements Serializable {

    /**
     * 方法名
     */
    private String methodName;

    /**
     * 参数
     */
    private Object[] args;

    /**
     * 参数的类型
     */
    private Class[] types;

    /**
     * class的路径
     */
    private String className;


}

consumer

启动应用发布端口消息

public class consumerApp {

    public static void main(String[] args) {
        ProxySocketClient proxySocketClient = new ProxySocketClient();
        OrderApi orderApi = proxySocketClient.proxyClient(OrderApi.class, "127.0.0.1", 12356);
        System.out.println(orderApi.getOrderName("发了一条消息!"));
    }
}

生成JDK代理

public class ProxySocketClient {

    /**
     * 动态代理发送socket连接
     */

    public <T> T proxyClient(final Class<T> clazz,String host,int port){
        return (T) Proxy.newProxyInstance(clazz.getClassLoader(),new Class<?>[]{clazz},new RemInvocationHandler(host,port));
    }
}

具体的代理类,发送socket

public class RemInvocationHandler implements InvocationHandler {

    //socket连接主机
    private String host;

    //端口
    private int port;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //封装rpc请求参数
        RpcRequest rpcRequest = new RpcRequest();
        rpcRequest.setArgs(args);
        rpcRequest.setClassName(method.getDeclaringClass().getName());
        rpcRequest.setTypes(method.getParameterTypes());
        rpcRequest.setMethodName(method.getName());
        RpcNetTransport rpcNetTransport = new RpcNetTransport(host,port);
        //发送请求
        System.out.println("发送请求");
        return rpcNetTransport.send(rpcRequest);
    }
}

把参数输入到socket中,并接收socket返回数据

public class RpcNetTransport{

    //socket连接主机
    private String host;

    //端口
    private int port;

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

    public Socket newSocket() throws IOException {
        return new Socket(host, port);
    }

    public Object send(RpcRequest rpcRequest) {
        ObjectInputStream inputStream = null;
        ObjectOutputStream outputStream = null;
        try {
            //建立socket连接
            Socket socket = newSocket();
            outputStream = new ObjectOutputStream(socket.getOutputStream());
            //把封装的参数数据输出到socket中
            outputStream.writeObject(rpcRequest);
            outputStream.flush();
            //接收socket返回数据
            inputStream = new ObjectInputStream(socket.getInputStream());
            return inputStream.readObject();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return null;
    }
}

provider

发布服务,待消费

public class ProducerApp {
    public static void main( String[] args ) {
        // new一个实例
        OrderApi orderApi = new OrderController();
        ProxySocketServer proxySocketServer = new ProxySocketServer();
        // 发布服务
        proxySocketServer.publisher(orderApi, 12356);
    }
}

RPC调用接口的实现类

public class OrderController implements OrderApi {


    @Override
    public String getOrderName(String name) {
        return "服务端响应:"+name;

    }
}

接收socket

public class ProxySocketServer {

    //开启多线程接收
    private final ExecutorService executorService = Executors.newCachedThreadPool();

    public void publisher(Object service,int port){
        ServerSocket serverSocket = null;

        try {
            while (true){
                //服务端接收socket建立连接
                serverSocket = new ServerSocket(port);
                Socket socket = serverSocket.accept();
                //从socket获取数据
                executorService.submit(new ProcessorHandler(service,socket));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(serverSocket != null){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

服务端具体接收执行方法实现

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() {
        ObjectInputStream objectInputStream = null;
        ObjectOutputStream objectOutputStream = null;
        try {
            //读取socket流转换
            objectInputStream = new ObjectInputStream(socket.getInputStream());
            //获取内容
            RpcRequest rpcRequest = (RpcRequest) objectInputStream.readObject();
            //执行调用方法
            Object res = this.invoke(rpcRequest);
            objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
            objectOutputStream.writeObject(res);
            objectOutputStream.flush();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }finally {
            if(objectOutputStream!= null){
                try {
                    objectOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(objectInputStream != null){
                try {
                    objectInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private Object invoke(RpcRequest rpcRequest) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //通过反射获取class
        Class<?> clazz = Class.forName(rpcRequest.getClassName());
        //获取方法(通过方法名+参数类型)
        Method method = clazz.getMethod(rpcRequest.getMethodName(), rpcRequest.getTypes());
        //传入参数(接口+方法参数)执行方法返回   ---provider端是具体接口的实现,调用接口返回
        return method.invoke(service,rpcRequest.getArgs());
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值