RPC简易学习
0.RPC简介
RPC, 英文全称:Remote Process Call. 中文全称:远程过程调用.
客户端通过网络请求调用远程服务端对外暴露服务。常用的两种RPC协议:TCP、HTTP。
举例描述:两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。
最简单的场景:通过百度搜索所需要的信息。
当我们在百度的搜索栏中填入所需要查找的信息时,浏览器客户端会创建一个网络请求,将所要查询的信息标识传给百度的远程服务器端。服务器得到请求之后,调用自身内部的处理操作,再将查询到的信息返回给浏览器,浏览器解析展示给用户。
1.RPC的优缺点
优点:
a) 解决单应用的性能瓶颈。
b) 实现应用之间的解耦,服务拆分。
c) 提升功能代码的复用性。
缺点:
a) 网络交互
b) 增加应用的复杂性
2.RPC实现流程
- 首先,要解决通讯的问题,主要是通过在客户端和服务器之间建立TCP连接,远程过程调用的所有交换的数据都在这个连接里传输。连接可以是按需连接,调用结束后就断掉,也可以是长连接,多个远程过程调用共享同一个连接。
- 第二,要解决寻址的问题,也就是说,A服务器上的应用怎么告诉底层的RPC框架,如何连接到B服务器(如主机或IP地址)以及特定的端口,方法的名称名称是什么,这样才能完成调用。比如基于Web服务协议栈的RPC,就要提供一个endpoint URI,或者是从UDDI服务上查找。如果是RMI调用的话,还需要一个RMI Registry来注册服务的地址。
- 第三,当A服务器上的应用发起远程过程调用时,方法的参数需要通过底层的网络协议如TCP传递到B服务器,由于网络协议是基于二进制的,内存中的参数的值要序列化成二进制的形式,也就是序列化(Serialize)或编组(marshal),通过寻址和传输将序列化的二进制发送给B服务器。
- 第四,B服务器收到请求后,需要对参数进行反序列化(序列化的逆操作),恢复为内存中的表达方式,然后找到对应的方法(寻址的一部分)进行本地调用,然后得到返回值。
- 第五,返回值还要发送回服务器A上的应用,也要经过序列化的方式发送,服务器A接到后,再反序列化,恢复为内存中的表达方式,交给A服务器上的应用
  
3.Code实现
定义接口:
/**
* Rpc接口
*
* @author apple
*/
public interface HelloService { String hello(String str); }
接口实现:
public class HelloServiceImpl implements HelloService {
    @Override
    public String hello(String str) {
        return return "hello " + str;
    }
}
RPC服务端:
public class RpcExporter {
    static Executor executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    public static void exporter(String hostName,int port) throws Exception{
        ServerSocket server = new ServerSocket();
        server.bind(new InetSocketAddress(hostName, port));
        try{
            while(true){
                executor.execute(new ExporterTask(server.accept()));
            }
        }finally{
            server.close();
        }
    }
    private static class ExporterTask implements Runnable{
        Socket client = null;
        public ExporterTask(Socket client){
            this.client = client;
        }
        @Override
        public void run() {
            ObjectInputStream input = null;
            ObjectOutputStream output = null;
            try {
                input = new ObjectInputStream(client.getInputStream());
                String interfaceName  = input.readUTF();
                Class<?> service = Class.forName(interfaceName);
                String methodName = input.readUTF();
                Class<?>[] parameterTypes = (Class<?>[])input.readObject();
                Object[] arguments = (Object[])input.readObject();
                Method method = service.getMethod(methodName, parameterTypes);
                Object result = method.invoke(service.newInstance(),arguments);
                output = new ObjectOutputStream(client.getOutputStream());
                output.writeObject(result);
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                if(output != null){
                    try {
                        output.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }finally{
                        output = null;
                    }
                }
                if(input != null){
                    try {
                        input.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }finally{
                        input = null;
                    }
                }
                if(client != null){
                    try {
                        client.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }finally{
                        input = null;
                    }
                }
            }
        }
    }
}
RPC客户端:
public class RpcImporter<S> {
    @SuppressWarnings("unchecked")
    public S importer(final Class<?> serviceClass,final InetSocketAddress addr){
        return (S) Proxy.newProxyInstance(serviceClass.getClassLoader(), new Class<?>[]{serviceClass.getInterfaces()[]}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Socket socket = null;
                ObjectOutputStream output = null;
                ObjectInputStream input = null;
                try{
                    socket = new Socket();
                    socket.connect(addr);
                    output = new ObjectOutputStream(socket.getOutputStream());
                    output.writeUTF(serviceClass.getName());
                    output.writeUTF(method.getName());
                    output.writeObject(method.getParameterTypes());
                    output.writeObject(args);
                    input = new ObjectInputStream(socket.getInputStream());
                    return input.readObject();
                }finally{
                    if(socket != null)
                        socket.close();
                    if(output != null)
                        output.close();
                    if(input != null)
                        input.close();
                }
            }
        });
    }
}
测试类:
public class RpcTest {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    RpcExporter.exporter("localhost", );
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        RpcImporter<HelloService> importer = new RpcImporter<HelloService>();
        HelloService service = importer.importer(HelloServiceImpl.class, new InetSocketAddress("localhost", ));
        while(true){
            System.out.println(service.hello("word"));
            try {
                Thread.sleep();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
执行结果:

4.常用的RPC框架
Java RMI
Web Service
Hessian
Thrift
Http Rest API
Dubbo
5.参考资料
谁能用通俗的语言解释一下什么是 RPC 框架?
https://www.zhihu.com/question/25536695
RPC简易学习的更多相关文章
- TensorFlow简易学习[3]:实现神经网络
		TensorFlow本身是分布式机器学习框架,所以是基于深度学习的,前一篇TensorFlow简易学习[2]:实现线性回归对只一般算法的举例只是为说明TensorFlow的广泛性.本文将通过示例Ten ... 
- 基于Netty的RPC简易实现
		代码地址如下:http://www.demodashi.com/demo/13448.html 可以给你提供思路 也可以让你学到Netty相关的知识 当然,这只是一种实现方式 需求 看下图,其实这个项 ... 
- 微软RPC技术学习小结
		RPC,即Remote Procedure Call,远程过程调用,是进程间通信(IPC, Inter Process Communication)技术的一种.由于这项技术在自己所在项目(Window ... 
- HTML DOM简易学习笔记
		文字版:https://github.com/songzhenhua/github/blob/master/HTML DOM简易学习笔记.txt 学习地址:http://www.w3school.co ... 
- JavaScript简易学习笔记
		学习地址:http://www.w3school.com.cn/js/index.asp 文字版: https://github.com/songzhenhua/github/blob/master/ ... 
- HTML简易学习笔记
		文字版地址 https://github.com/songzhenhua/github/blob/master/HTML简易学习笔记.txt 
- 简易RPC框架-学习使用
		*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ... 
- rpc简易实现-zookeeper
		一.RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.RPC协议假定某些传输协议的存在,如TCP或UDP, ... 
- Dubbo简易学习
		0. Dubbo简易介绍 DUBBO是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,是阿里巴巴SOA服务化治理方案的核心框架,每天为2,000+个服务提供3,000,000, ... 
随机推荐
- twig 模板引擎使渲染视图更加优雅
			在使用 laravel 的时候接触过 blade 模板引擎.在学习的时候,接触到了另外一个强大的模板引擎:twig 官网:https://twig.sensiolabs.org/ 中文手册:http: ... 
- 判断页面是否被嵌入iframe里面
			最近在做一个项目,是一个小型的后台管理系统,这个系统可以单独打开,也可以嵌入公司大型的后台管理项目里面 这样就存在一个问题,在被嵌入大的后台管理系统后,不用显示该页面顶部导航栏和左侧的菜单栏 所以我们 ... 
- POJ-2785 Values whose Sum is 0 Hash表
			题目链接:https://cn.vjudge.net/problem/POJ-2785 题意 给出四组数,每组有n个数 现从每组数中取一个数作为a,b,c,d 问有几组这样的a+b+c+d=0 思路 ... 
- 紫书 例题 10-22 UVa 1640(数位统计)
			这道题的题解有几个亮点 一个是每次只统计一个数字来简化思维 一个是统计当前位数的时候分三个部分来更新答案 具体看代码,有注释 #include<cstdio> #include<cs ... 
- C语言操作数截断
			//测试截断 #include <stdio.h> int main() { int a = 0x80000001; unsigned int b = 0x80000001; printf ... 
- 08-for循环
- 三 Client 如何找到正确的 Region Server
			客户端在进行put.delete.get等操作的时候,它都需要数据到底存在哪个Region Server上面,这个定位的操作是通过 Connection.locateRegion方法来完成的. loc ... 
- easyui combobox 取值
			easyui combobox 取值 var zhudaoci = $.trim($('#spanZhudaociId').combobox('getValue')); 学习了:http://blog ... 
- Oracle TIMESTAMP的处理
			public class Test { private static final SimpleDateFormat FORMAT = new SimpleDateFormat("yyyy-M ... 
- SharePoint创建Alternate Access Mapping (AAM)备用訪问映射
			SharePoint创建Alternate Access Mapping (AAM)备用訪问映射 SharePoint的仓库是SQL Server中的内容数据库.这些数据库储存着组织全 ... 
