一步一步了解RPC之服务端

本文介绍了作者自行构建的一个简易RPC框架。该框架包括服务端发布服务及客户端调用的完整流程,通过反射机制实现了跨JVM的服务调用。文章详细展示了服务端与客户端的具体实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       公司项目中使用了分布式,采用的是猎聘网的一套框架,并未使用Dubbo,SpringCloud等流行的技术框架。在使用过程中,仅仅会常用的jar包升级、服务调用等,对具体的RPC实现原理没有真正的理解。这两天趁着周末不加班,学习了一下RPC的知识,实现了一个小的demo帮助理解。

      分布式系统中,有下面几种角色:Consumer,Provider和注册中心。这里以前两种为重点介绍。在同一JVM中,类与类的调用关系通常为new出一个实例,然后调用实例方法。在分布式应用中,由于实体不存在于一个项目,类之间调用关系不能通过new来实现,因此需要通过代理类进行服务调用。

     首先介绍服务端rpc-server端情况,服务端发布服务,对Consumer的调用进行处理并返回。

     在服务端中存在一个接口IHgHello及其实现类HgHelloImpl,如下所示:

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


public class HgHelloImpl implements IHgHello {

    @Override
    public String sayHello(String name) {
        return "这里是提供方,hello," + name;
    }
}

  服务端需要对IHgHello接口进行发布,让消费方进行调用。这里的类为RpcProxyServer,其主要负责接收客户端的socket连接并进行处理,具体的处理类为ProcessHandler。

public class RpcProxyServer {

    ExecutorService executorService  = Executors.newCachedThreadPool();

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

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



public class ProcessorHandler implements  Runnable {

    Socket socket;
    Object service;

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

    @Override
    public void run() {
        System.out.println("begin process handler");
        ObjectInputStream inputStream = null;
        ObjectOutputStream outputStream = null;
        try {
            inputStream = new ObjectInputStream(socket.getInputStream());
            RPCRequest request = (RPCRequest) inputStream.readObject();
            Object result = invoke(request);

            outputStream = new ObjectOutputStream(socket.getOutputStream());
            outputStream.writeObject(result);
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException 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();
                }
            }
        }

    }

    private Object invoke(RPCRequest request) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Object[] args = request.getParams();
        Class<?>[] types = new Class[args.length];
        for(int i=0;i<args.length;i++){
            types[i] = args[i].getClass();
        }
        // 调用类
        // request.getClassName();
        Method method = service.getClass().getMethod(request.getMethodName(),types);
        return method.invoke(service,args);
    }
}

 当Consumer连接上时,调用sayHello方法,服务端处理类ProcessorHandler通过反射获取调用的service类名、方法名和参数,通过原生的序列化和反序列化方法,进行结果返回。其中发布服务的方法为:

    public static void main(String[] args) throws IOException {
        IHgHello iHgHello = new HgHelloImpl();
        RpcProxyServer rpcProxyServer = new RpcProxyServer();
        rpcProxyServer.publisher(iHgHello,8080);
        System.out.println(iHgHello.sayHello("haha,我是服务方"));
    }

这样服务端的实现已经完成,下面进行客户端的实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值