zoukankan      html  css  js  c++  java
  • RPC简述

    RPC简述

    提问:什么是RPC?

    PRC是一种远程过程调用框架,相比远程调用,我们可以先理解本地调用,本地调用就是方法A和方法B都写在同一个工程中,然后A可以调用B。但是如果A方法和B方法是属于不同工程中,则需要进行远程调用。

    误解:如A工程中需要调用B工程中的方法,一般是将B工程打一个包,然后A中会引入这个包,然后就可以调用到B中的方法了,这种两个工程间没有网络通信则只能称为远程方法的引用,只有两个工程存在网络通信,A调用B的方法并且是B处理后返回给A,才能称为远程过程调用!!

    RPC远程调用原理

    一、RPC是怎么做到远程调用的,其原理是什么?

    追根究底,R客户端与服务端建立TCP链接,相比于HTTP通信协议少去应用层的许多东西。数据的传输就是通过这个TCP的链接。

    Client:服务消费方

    Server:服务提供方

    (1).Client以调用本地服务方式调用远程API

    (2).Client Stub负责接收参数,方法等,将其封装(编码)成能够进行网络传输的消息体

    (3).Client Stub负责网络寻址,将消息体发送对应的服务端

    (4).Server Stub负责接收消息,并解码成服务端能够识别的信息,调用对应的服务端方法

    (5).Server本地服务将调用结果发送给Server Stub

    (6).Server Stub将返回结果包装成消息体返回给Client Stub

    (7).Client Stub接收消息并进行解码

    (8).Client获取到最终调用结果

    二、实例运行

    举例:实现两个本地工程之间的远程调用,如下是RpcProvider工程的代码

    public interface BatterCakeService {
        public String sellBatterCake(String name);
    }
    
    public class BatterCakeServiceImpl implements  BatterCakeService{
        public String sellBatterCake(String name) {
            return name+"味道很赞";
        }
    }
    
    public class RpcProvider {
        //存储注册的服务列表
        private static List<Object> serviceList;
    
        /**
         * 发布rpc服务
         * @param
         * @param port
         * @throws Exception
         */
        public static void export(int port,Object... services) throws Exception {
            serviceList= Arrays.asList(services);
            //创建本地服务,端口20006
            ServerSocket server = new ServerSocket(port);
            Socket client = null;
            while (true) {
                //阻塞等待输入,一直监听,如果有服务请求,则返回,否则一直等待
                client = server.accept();
                //每一个请求,启动一个线程处理
                new Thread(new ServerThread(client,serviceList)).start();
            }
        }
    }
    
    public class ServerThread implements Runnable {
        private Socket client=null;
        private List<Object> serviceList=null;
        public ServerThread(Socket client,List<Object> service)
        {
            this.client=client;
            this.serviceList=service;
        }
        @Override
        public void run() {
            ObjectInputStream input=null;
            ObjectOutputStream output=null;
            try {
                    //创建请求服务的输入输出流
                    input=new ObjectInputStream(client.getInputStream());
                    output=new ObjectOutputStream(client.getOutputStream());
                // 读取客户端要访问那个service
                Class serviceClass = (Class)input.readObject();
    
                // 找到该服务类
                Object obj = findService(serviceClass);
                if(obj==null)
                {
                    output.writeObject(serviceClass.getName() + "服务未发现");
                }else {
    
                    String methodName = input.readUTF();
                    Class<?>[] parameterTypes = (Class<?>[]) input.readObject();
                    Object[] arguments = (Object[]) input.readObject();
                    Method method = obj.getClass().getMethod(methodName, parameterTypes);
                    Object result = method.invoke(obj, arguments);
                    output.writeObject(result);
                }
    
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                try {
                    client.close();
                    input.close();
                    output.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
                }
    
    
        }
    
        private Object findService(Class serviceClass) {
            // TODO Auto-generated method stub
            for (Object obj : serviceList) {
                boolean isFather = serviceClass.isAssignableFrom(obj.getClass());
                if (isFather) {
                    return obj;
                }
            }
            return null;
        }
    
    }
    
    

    主函数:

    public class RpcBootStrap {
        public static void main(String[] args) throws Exception {
            BatterCakeService batterCakeService =new BatterCakeServiceImpl();
            //发布卖煎饼的服务,注册在20006端口
            RpcProvider.export(20006,batterCakeService);
        }
    }
    

    运行主函数,保持服务提供方的监听

    服务消费方consumer代码:consumer中会调用provider中的sellBatterCake(String name)方法,可以从如下看出,consumer中并没有sellBatterCake(String name)方法的实现

    public interface BatterCakeService {
        public String sellBatterCake(String name);
    }
    
    public class ProxyHandler implements InvocationHandler {
        private String ip;
        private int port;
    
        public ProxyHandler(String ip, int port) {
            // TODO Auto-generated constructor stub
            this.ip = ip;
            this.port = port;
        }
    
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Socket socket = new Socket(this.ip, this.port);
            ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
            ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
            try {
                output.writeObject(proxy.getClass().getInterfaces()[0]);
                output.writeUTF(method.getName());
                output.writeObject(method.getParameterTypes());
                output.writeObject(args);
                output.flush();
                Object result = input.readObject();
                if(result instanceof Throwable) {
                    throw (Throwable) result;
                }
                return result;
            } finally {
                socket.shutdownOutput();
            }
        }
    
    
    
    }
    
    
    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);
        }
    }
    
    public class RpcTest {
        public static void main(String[] args) {
            BatterCakeService batterCakeService=RpcConsumer.getService(BatterCakeService.class, "127.0.0.1", 20006);
            String result=batterCakeService.sellBatterCake("双蛋");
            System.out.println(result);
        }
    }
    

    运行consumer中的主函数:

    上述可以看出是consumer远程调用了provider中的sellBatterCake()方法!!!

  • 相关阅读:
    iOS 证书错误 Certificates下面的 App Store and Ad Hoc是灰的?? 点不了
    iOS 发布证书错误 Your build settings specify a provisioning profile with the UUID, no provisioning profile was found
    不能修改“System Roots”钥匙串 即下载的.cer 文件添加不到钥匙串
    修改 “嗨加游-Prefix.pch” 或者 “嗨加游-Info.plist ” 方法
    Java基础1(2015-8-2)
    认识modernizr----前端
    VS2013的C#项目与SQL Server2012无法连接的问题
    安装完SQL Server 2012后,由Windows身份验证设置为混合型的身份验证
    C#项目,在controller文件夹右击鼠标没有“添加控制器”的问题
    复制已存在的数据库结构(不包括库中的数据)
  • 原文地址:https://www.cnblogs.com/lixuan1998/p/11369241.html
Copyright © 2011-2022 走看看