RPC 框架

RPC 框架

    • RPC 概念
    • 手写RPC框架
      • 设计模块
      • 涉及到的技术
      • 具体实现
      • 破产版RPC
        • 服务端
        • 客户端

RPC 概念

RPC(Remote Procedure Call Protocool)远程过程调用。
为什么用RCP
各个模块可能部署在不同的主机上(主要的原因是不在一个内存空间,不能直接调用),需要远程通信访问,通过HTTP或者RPC的方式
调用的流程
1、解决通信问题,即建立TCP链接,通过链接进行数据传输
2、解决寻址问题,如何寻找B服务器上被调用的方法,可以理解为对外暴露方法的方式
3、客户端序列化传输到服务器
4、服务器反序列化解析处理结果,序列化返回
5、客户端反序列化解析结果
流行的RPC框架
Dubbo、Thrif(跨语言)、WebService(基于SOAP协议)、Hessian、grpc都是基于RPC原理实现的

手写RPC框架

设计模块

客户端和服务端都可以分成4层,最底层是socket接受发送请求,上面一层是序列化和反序列化,再往上是代理层,最顶端是用户调用层

涉及到的技术

1、通信(TCP协议)
2、序列化和反序列化,回顾之前的如(java原生方法,avro,protobuf,json,xml)
3、IO(BIO/NIO/AIO)
4、反射
5、代理
6、暴露服务:ip/端口/目标类/参数,如WebService对应的wsdl,dubbo对应//url

具体实现

创建一个两个maven项目rpc-server/rpc-client
server有两个模块api和provider,api对外提供接口,provider发布服务

破产版RPC

服务端

RPC 框架_第1张图片
api
RPC 框架_第2张图片
RPC 框架_第3张图片
RpcRequest

public class RpcRequest implements Serializable
{
    private String className;

    private String methodName;

    private Object[] parameters;

    public String getClassName()
    {
        return className;
    }

    public void setClassName(String className)
    {
        this.className = className;
    }

    public String getMethodName()
    {
        return methodName;
    }

    public void setMethodName(String methodName)
    {
        this.methodName = methodName;
    }

    public Object[] getParameters()
    {
        return parameters;
    }

    public void setParameters(Object[] parameters)
    {
        this.parameters = parameters;
    }

    @Override
    public String toString()
    {
        return "RpcRequest{" + "className='" + className + '\'' + ", methodName='" + methodName + '\'' + ", parameters=" + Arrays.toString(parameters) + '}';
    }
}

provider
RPC 框架_第4张图片
依赖api
RPC 框架_第5张图片
provider的主要功能
开启一个线程池不断的处理客户端的请求
启动服务App App

 public static void main(String[] args)
    {
        HelloService service = new HelloServiceImpl();
        RpcProxyServer proxyServer=new RpcProxyServer();
        proxyServer.publiser(service,8011);
    }

代理服务 RpcProxyServer

1、线程池:

//创建线程池
ExecutorService threadPool = Executors.newFixedThreadPool(5);

2、循环阻塞

serverSocket = new ServerSocket(port);
while(true)
{
 	Socket socket = serverSocket.accept();
 	threadPool.execute(new ProcessorHandler(socket,service));
}

3、处理输入输出流的线程 ProcessorHandler

package com.gupao.rpc;

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

/**
 * @Autor : heyanfeng22
 * @Description :
 * @Date:Create:in 2019/6/28 15:12
 * @Modified By:
 */
public class ProcessorHandler implements Runnable
{
    private Socket socket;

    private Object service;

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

        this.service = service;
    }

    @Override
    public void run()
    {
        //处理请求
        ObjectInputStream objectInputStream=null;
        ObjectOutputStream objectOutputStream=null;

        try
        {
            objectInputStream = new ObjectInputStream(socket.getInputStream());
            RpcRequest rpcRequest = (RpcRequest) objectInputStream.readObject();
            //反射调用本地服务
            Object result=invoke(rpcRequest);

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

        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (objectInputStream!=null)
            {
                try
                {
                    objectInputStream.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }

            if(objectOutputStream!=null)
            {
                try
                {
                    objectOutputStream.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }

        }

    }

    private Object invoke(RpcRequest rpcRequest) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException
    {
        String className = rpcRequest.getClassName();
        String MethdName = rpcRequest.getMethodName();
        Object[] parameters = rpcRequest.getParameters();//拿到请求参数

        //获得每个参数的类型
        Class[] types = new Class[parameters.length];

        for (int i=0;i

客户端

RPC 框架_第6张图片
依赖api
RPC 框架_第7张图片
客户端访问 App

public static void main(String[] args)
    {
        //通过代理类调用服务
        RpcProxyClient proxyClient = new RpcProxyClient();

        HelloService service = proxyClient.createClient(HelloService.class,"localhost",8011);

        String result = service.sayHello("哈哈哈");

        System.out.println(result);

    }

代理类 RpcProxyClient

public class RpcProxyClient
{
    public  T createClient(Class inerfaceClazz,String ip,int port)
    {
        return (T)Proxy.newProxyInstance(inerfaceClazz.getClassLoader(),new Class[]{inerfaceClazz},new RemoteInvocationHandler(ip,port));

    }
}

代理实现类 RemoteInvocationHandler

public class RemoteInvocationHandler implements InvocationHandler
{
    private String host;

    private int port;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    {
        //请求会进入到这里
        System.out.println("come in");

        //在这里处理请求
        //请求数据的包装
        RpcRequest rpcRequest=new RpcRequest();
        rpcRequest.setClassName(method.getDeclaringClass().getName());
        rpcRequest.setMethodName(method.getName());
        rpcRequest.setParameters(args);
        //远程通信
        RpcNetTransport netTransport=new RpcNetTransport(host,port);
        Object result=netTransport.send(rpcRequest);

        return result;
    }
}

具体请求类 RpcNetTransport

public class RpcNetTransport
{


    private String host;
    private int port;

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



    public Object send(RpcRequest request){
        Socket socket=null;
        Object result=null;
        ObjectOutputStream outputStream=null;
        ObjectInputStream inputStream=null;

        try {
            socket=new Socket(host,port); //建立连接

            outputStream =new ObjectOutputStream(socket.getOutputStream());//网络socket
            outputStream.writeObject(request); //序列化()
            outputStream.flush();

            inputStream=new ObjectInputStream(socket.getInputStream());
            result=inputStream.readObject();


        } catch (IOException e) {
            e.printStackTrace();
        } catch (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 result;

    }
}

运行
服务端收到请求:
RPC 框架_第8张图片
客户端收到回应:
在这里插入图片描述
到这里破产版的RPC框架就写完了

你可能感兴趣的:(RPC,分布式(基础))