2020-10-11

手动实现一个RPC框架


前言

RPC = Remote Procedure Call,远程调用服务协议

RPC跟HTTP服务协议有什么区别可以看看https://blog.csdn.net/wangyunpeng0319/article/details/78651998 ,文章里说的很好也很清楚,总结来说,RPC服务效率肯定高于HTTP,一般用于分布式服务系统中,但是HTTP使用起来肯定复杂度是低于RPC框架的。


提示:以下是本篇文章正文内容,下面案例可供参考

一、RPC服务的远程调用过程

作为一个开发者,平时HTTP服务我们会经常用到,比如一个服务A提供了一个查询接口API,另外一个服务B需要去调用这个API接口,那么如果用RPC实现的话,就需要两个服务有共同约定好的接口,然后服务A去实现这个接口,服务B去调用

二、具体代码实现

1.模块

代码如下(示例):

package com.rpc.study.demo.localclient;

import com.rpc.study.demo.UserApi;
import com.rpc.study.demo.server.User;

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


public class LocalMain {

    //本地调用远程服务
    public  static  void  main(String args[]){
        UserApi userApi = (UserApi) rpc(UserApi.class);
        User user= userApi.selectById(1);
        System.out.println("本地输出远程调用结果:\n"+user.toString());
    }

    public  static Object rpc(final Class clazz){
        // Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
        return Proxy.newProxyInstance(clazz.getClassLoader(),new Class[]{clazz},new InvocationHandler() {
            /*
             * @param proxy  代理对象
             * @param method    代理的方法对象
             * @param args  方法调用时参数
             * @return
             * @throws Throwable
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Socket socket=new Socket("127.0.0.1",8888);
                String className=clazz.getName();
                String  methodName=method.getName();
                Class<?>[] parameterTypes=method.getParameterTypes();

                ObjectOutputStream objectOutputStream=new ObjectOutputStream(socket.getOutputStream());
                objectOutputStream.writeUTF(className);
                objectOutputStream.writeUTF(methodName);
                objectOutputStream.writeObject(parameterTypes);
                objectOutputStream.writeObject(args);

                ObjectInputStream objectInputStream=new ObjectInputStream(socket.getInputStream());
                Object o=objectInputStream.readObject();
                objectInputStream.close();
                objectOutputStream.close();
                return o;
            }
        });
    }
}
package com.rpc.study.demo.server;

import com.rpc.study.demo.UserApi;

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


public class ServerMain {

    public static void main(String[] args) {
        try {
            ServerSocket serverSocket=new ServerSocket(8888);
            System.out.println("启动远程服务监听...");
            //监听客户端发来消息
            while (true){
                Socket socket=serverSocket.accept();
                ObjectInputStream objectInputStream=new ObjectInputStream(socket.getInputStream());
                //读取客户端传输协议包
                String className=objectInputStream.readUTF();
                String methodName=objectInputStream.readUTF();
                Class<?>[] parameterTypes=(Class<?>[])objectInputStream.readObject();
                Object[] arguments= (Object[]) objectInputStream.readObject();

                Class clazz=null;
                //服务注册:API到具体实现的映射
                if(className.equals(UserApi.class.getName())){
                    clazz=UserService.class;
                }
                //传入方法名,方法参数类型获得方法对象
                Method method=clazz.getMethod(methodName,parameterTypes);
                //传入实现类对象,方法参数数组,方法对象执行获得返回结果对象
                Object result=method.invoke(clazz.newInstance(),arguments);

                ObjectOutputStream objectOutputStream=new ObjectOutputStream(socket.getOutputStream());
                objectOutputStream.writeObject(result);
                objectOutputStream.flush();

                objectInputStream.close();
                objectOutputStream.close();
                socket.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package com.rpc.study.demo.server;

import java.io.Serializable;



public class User implements Serializable {
    private  Integer id;
    private  String username;
    private  String message;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", message='" + message + '\'' +
                '}';
    }
}
package com.rpc.study.demo.server;

import com.rpc.study.demo.UserApi;


public class UserService implements UserApi {

    @Override
    public User selectById(Integer id) {
        User user=new User();
        user.setUsername("张三");
        user.setId(id);
        user.setMessage("张三是胖子");
        System.out.println("UserService调用了selectById()方法查询用户.....");
        return user;
    }
}
package com.rpc.study.demo;

import com.rpc.study.demo.server.User;


public interface UserApi {
    User selectById(Integer id);
}
 
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值