我是靠谱客的博主 爱笑书包,最近开发中收集的这篇文章主要介绍【手写RPC框架(三)】实现服务注册,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录

    • 一、实现简单服务注册功能
      • 1.1 服务端
        • 1.1.1 发布rpc服务
      • 1.2 注册中心
        • 1.2.1 实现rpc服务注册
        • 1.2.2 注册服务同时,开启线程,监听客户端请求
      • 1.3 客户端
        • 1.3.1 实现代理类,在代理类中请求服务
        • 1.3.2 获取代理对象
      • 1.4 通过RPC远程调用(测试示例,客户端)

一、实现简单服务注册功能

quadquad RPC框架一般由服务端,消费端,注册中心三部分组成。注册中心负责持久化服务名称,IP地址以及端口等。本次只实现简单的服务注册功能。
quadquad 本篇文章实现简单的注册中心,即注册中心中仅仅存放服务,没有存放地址、端口信息。而接口、实现类和序列化在前面两篇文章中已经实现,不再赘述。

1.1 服务端

1.1.1 发布rpc服务

  • 将端口信息和服务信息提交注册中心
public class RpcBootStrap {
    public static void main(String[] args) throws IOException {
        CalculatorService calculator=new CalculatorServiceImpl();
        RpcProvider.export(8081,calculator);
    }
}

1.2 注册中心

  • 服务端发布服务后,以列表形式在注册中心进行注册,只存放服务信息并传入服务地址
  • 根据服务地址,监听socket端口,是否收到客户端请求信息。
  • 若收到客户端请求,开启新的线程,首先检查注册中心中是否有客户端请求的服务,若无则返回没有服务。
  • 若有,则处理序列化后的请求信息(此时数据是通过网络发到服务端处理的),通过反射调用服务端相关服务方法,并返回服务信息处理结果。

1.2.1 实现rpc服务注册

public class RpcProvider {
    //负责存储服务列表
    private static List<Object> serviceList;

    //发布一个rpc服务
    public static void export(int port,Object... service) throws IOException {
        serviceList= Arrays.asList(service);
        ServerSocket server = new ServerSocket(port);
        Socket client=null;
        while (true){
            client=server.accept();
            new Thread(new ServerThread(client,serviceList)).start();
        }
    }

1.2.2 注册服务同时,开启线程,监听客户端请求

  • 此时服务端客户端通过socket进行RPC通信
  • 接收客户端请求服务信息
  • 检查注册中心是否存有客户端存有的请求服务信息
  • 若有通过反射调用相关服务,并将计算结果序列化后传回客户端
public class ServerThread implements Runnable{
    private Socket client=null;
    private List<Object> serviceList=null;
    public ServerThread(Socket client,List<Object> services){
        this.client=client;
        this.serviceList=services;
    }
    public void run(){
        ObjectInputStream objectInputStream=null;
        ObjectOutputStream objectOutputStream=null;
        try{
            objectInputStream=new ObjectInputStream(client.getInputStream());
            objectOutputStream=new ObjectOutputStream(client.getOutputStream());
            RpcSerializable rpcSerializable=(RpcSerializable)objectInputStream.readObject();
            // 读取类名
            Class serviceClass=(Class) rpcSerializable.getClassName();
            Object obj=getService(serviceClass);
            if(obj==null){
                throw new Exception("not service");
            }
            // 读取方法名
            String methodName=rpcSerializable.getMethodName();
            // 读取方法入参类型
            Class<?>[] parameterTypes=rpcSerializable.getParameterTypes();
            // 读取方法调用入参
            Object[] parameters=rpcSerializable.getArguments();
            System.out.println(String.format("收到消费者远程调用请求:类名 = {%s},方法名 = {%s},调用入参 = %s,方法入参列表 = %s",
                    serviceClass, methodName, Arrays.toString(parameters), Arrays.toString(parameterTypes)));
            Method method = obj.getClass().getMethod(methodName,parameterTypes);
            Object invoke = method.invoke(obj, parameters);
            System.out.println("方法调用结果:" + invoke);
            objectOutputStream.writeObject(invoke);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Object getService(Class servicesClass){
        for(Object obj:serviceList){
            boolean isFather=servicesClass.isAssignableFrom(obj.getClass());
            if(isFather){
                return obj;
            }
        }
        return null;
    }
}

1.3 客户端

  • 客户端向注册中心订阅服务地址并发送服务请求

1.3.1 实现代理类,在代理类中请求服务

  • ip、port作为参数
public class ProxyHandler implements InvocationHandler {
    private String ip;
    private int port;

    public ProxyHandler(String ip, int port) {
        this.ip = ip;
        this.port = port;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Exception {
        Socket socket = new Socket(ip,port);
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
        RpcSerializable rpcSerializable = new RpcSerializable(proxy.getClass().getInterfaces()[0], method.getName(), method.getParameterTypes(), args);
        objectOutputStream.writeObject(rpcSerializable);
        ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());
        return inputStream.readObject();
    }
}

1.3.2 获取代理对象

public class RpcConsumer {
    public static <T> T getService(Class<T> clazz,String ip,int port) {
        ProxyHandler proxyHandler =new ProxyHandler(ip,port);
        return (T) Proxy.newProxyInstance(RpcConsumer.class.getClassLoader(), new Class<?>[] {clazz}, proxyHandler);
    }
}

1.4 通过RPC远程调用(测试示例,客户端)

public class RpcTest {
    public static void main(String[] args) {
        CalculatorService calculator= RpcConsumer.getService(CalculatorService.class,"127.0.0.1",8081);
        int res=calculator.add(100,86);

        System.out.println(res);
    }
}

最后

以上就是爱笑书包为你收集整理的【手写RPC框架(三)】实现服务注册的全部内容,希望文章能够帮你解决【手写RPC框架(三)】实现服务注册所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(65)

评论列表共有 0 条评论

立即
投稿
返回
顶部