2步实现RPC框架(Maven+Java+Protostuff)

前言

RPC说到底就是远程调用,要实现远程调用,只需要2步。

1.消费者传输(类名+方法名+参数)给服务端

2.服务端收到(类名+方法名+参数),执行具体方法,将执行结果返回给消费者。

市面上所有的RPC框架都是上述两步,不一样的只是传输协议,也就是怎么传输(类名+方法名+参数)。一般就是HTTP协议和自研协议,如SpringCloud使用HTTP,dubbo使用自研。

我们这里使用,Socket+Protostuff,附件我会上传(环境是JDK1.8),尽可能的写的简单明了,强烈建议大家下载下来用idea导进去,对照学习。

一、项目总体架构

一般来说,生产环境下,消费端+服务端+公用接口,是分成3个子模块的,服务端和消费端依赖公用接口(二方包),服务端实现接口,消费端调用接口。

二、具体实现

1.服务端

1.1 收到客户端的(类名+方法名+参数)

1.2 通过Java反射执行方法

1.3 返回结果

ServerSocket serverSocket = new ServerSocket(8888);

while (true) {
    Socket socket = serverSocket.accept();
    
    InputStream inputStream = socket.getInputStream();
    
    //1.1 收到客户端的(类名+方法名+参数)
    TransferObject transferObject = SerializingUtil.deserialize(inputStream, TransferObject.class);

    String apiClassName = transferObject.getApiName();
    String methodName = transferObject.getMethodName();
    Class[] paramTypes = transferObject.getParamTypes();
    Object[] args4Method = transferObject.getArgs();
    Class clazz = null;
    if (apiClassName.equals(IUserService.class.getName())) {
        clazz = UserServiceImpl.class;
    }
    Method method = clazz.getMethod(methodName, paramTypes);

    //1.2 通过反射执行方法
    Object returnObject = method.invoke(clazz.newInstance(), args4Method);
    
    //1.3 返回结果
    OutputStream outputStream = socket.getOutputStream();
    outputStream.write(SerializingUtil.serialize(returnObject));
    
    outputStream.flush();
    outputStream.close();
    inputStream.close();
    socket.close();
}

 

2.消费端

2.1 发送(类名+方法名+参数)给服务端

注意这里的IUserService是不能new的,因为消费端没有实现类,只能通过Java动态代理。

动态代理的简要意思是,对于没有实现类的接口来说,可以代为实现一个“虚拟”类,执行方法,返回结果。

这里的执行方法,可以是本地的,也可以是远程的,是Java代码就行。RPC的核心就是这里。

2.2 收到服务的执行结果

public class ConsumerStarter {
    public static void main(String[] args) {
        IUserService userService = (IUserService) ProxyFactory.getProxyInstance(IUserService.class);

        User temp = new User();
        temp.setId(1);
        temp.setName("张三");

        userService.add(temp);
        User user = userService.findById(1);

        System.out.println(user);
    }
}
public class ProxyFactory {
    public static Object getProxyInstance(Class clazz) {
        return Proxy.newProxyInstance(
                clazz.getClassLoader(),
                new Class[]{clazz},
                (proxy, method, args) -> {
                    Socket socket = new Socket("127.0.0.1", 8888);

                    String apiName = clazz.getName();
                    String methodName = method.getName();
                    Class returnClass = method.getReturnType();
                    Class[] paramTypes = method.getParameterTypes();

                    TransferObject transferObject = new TransferObject();
                    transferObject.setApiName(apiName);
                    transferObject.setMethodName(methodName);
                    transferObject.setParamTypes(paramTypes);
                    transferObject.setArgs(args);

                    2.1 发送(类名+方法名+参数)给服务端
                    OutputStream outputStream = socket.getOutputStream();
                    outputStream.write(SerializingUtil.serialize(transferObject));
                    outputStream.flush();
                    socket.shutdownOutput();

                    2.2 收到服务的执行结果
                    InputStream inputStream = socket.getInputStream();
                    Object returnObject = SerializingUtil.deserialize(inputStream, returnClass);

                    inputStream.close();
                    outputStream.close();
                    socket.close();
                    return returnObject;
                });
    }
}

 

结语

我不喜欢blog一堆代码,因为重点是思路,代码能体现思路就行,具体的代码建议大家下载下来,亲自跑一跑。修改修改,比如我使用的是Protostuff序列化,你可以修改为JSON试试,或者用Java自带的序列化。

我使用的是socket,你换成HTTP试试,或者用netty试试。

RPC和核心就是 消费端【Java动态代理】+服务端【Java反射】

工程已上传,审核中,也可以去GitHub看。

项目地址:https://github.com/cklogic/blog/tree/master/rpc-demo

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值