谁能用通俗的语言解释一下什么是 RPC 框架
转载自知乎:https://www.zhihu.com/question/25536695
知乎上很多问题的答案还是很好的,R大就经常在上面回答问题~
谁能用通俗的语言解释一下什么是 RPC 框架?
你的题目是RPC框架,首先了解什么叫RPC,为什么要RPC,RPC是指远程过程调用,也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。
比如说,一个方法可能是这样定义的:
Employee getEmployeeByName(String fullName)
那么:
- 首先,要解决通讯的问题,主要是通过在客户端和服务器之间建立TCP连接,远程过程调用的所有交换的数据都在这个连接里传输。连接可以是按需连接,调用结束后就断掉,也可以是长连接,多个远程过程调用共享同一个连接。
- 第二,要解决寻址的问题,也就是说,A服务器上的应用怎么告诉底层的RPC框架,如何连接到B服务器(如主机或IP地址)以及特定的端口,方法的名称是什么,这样才能完成调用。比如基于Web服务协议栈的RPC,就要提供一个endpoint URI,或者是从UDDI服务上查找。如果是RMI调用的话,还需要一个RMI Registry来注册服务的地址。
- 第三,当A服务器上的应用发起远程过程调用时,方法的参数需要通过底层的网络协议如TCP传递到B服务器,由于网络协议是基于二进制(0101)的,内存中的参数的值要序列化成二进制的形式,也就是序列化(Serialize)或编组(marshal),通过寻址和传输将序列化的二进制发送给B服务器。
- 第四,B服务器收到请求后,需要对参数进行反序列化(序列化的逆操作),恢复为内存中的表达方式,然后找到对应的方法(寻址的一部分)进行本地调用,然后得到返回值。
- 第五,返回值还要发送回服务器A上的应用,也要经过序列化的方式发送,服务器A接到后,再反序列化,恢复为内存中的表达方式,交给A服务器上的应用
为什么RPC呢?就是无法在一个进程内,甚至一个计算机内通过本地调用的方式完成的需求,比如不同的系统间的通讯,甚至不同的组织间的通讯。由于计算能力需要横向扩展,需要在多台机器组成的集群上部署应用,
RPC的协议有很多,比如最早的CORBA,Java RMI,Web Service的RPC风格,Hessian,Thrift,甚至Rest API。
关于Netty
而Netty框架不局限于RPC,更多的是作为一种网络协议的实现框架,比如HTTP,由于RPC需要高效的网络通信,就可能选择以Netty作为基础。除了网络通信,RPC还需要有比较高效的序列化框架,以及一种寻址方式。如果是带会话(状态)的RPC调用,还需要有会话和状态保持的功能。
(图片来源:
这样每一层都有一个处理接口,都可以进行不同的操作,比如身份认证,加解密,日志,流控,将不同的处理实现像拼积木那样插接起来就可以实现一个网络协议了(快速开发)。每一层都有自己的实现,上层不需要关注面向网络的操作(可维护)。Netty已经提供了很多实现。
(图片来源:
当然Netty还有许多好处,比如对非阻塞IO(NIO)的支持,比如在链上传递时最大程度的减少buffer的copy(高性能)。
-----------------------
我们可以推断演进一下
====
1. A B 两个进程之间需要进行数据交换。
2.于是我们想出来在某个内存区域划出一个空间,然后向该空间中写入和读取数据。(共享文件也可以)(常见的socket就是这一共享内存的抽象,只是现在大多指网络通路)
3.A B 通信完成。
====
4.A B需要完成更复杂的交互
5.于是我们指定一个协议,A B 根据该协议对数据的进行编码解码,根据协议内容做出决策。
====
6.发现协议过于复杂(比如 编号1代表调用 a函数,编号2代表b函数)
7.试图优化协议,将函数参数和调用的函数名称作为协议的一部分,函数返回值类似
8.RPC达成
=====
9.表现出来的特性就是,object invok(parameter),就代表了,序列化 parameter 对象到中间格式,利用远程服务器的 invok 函数进行处理 ,同时将返回的数据解码生成 object对象。
======总结=====
RPC 在整个过程中,体现了逐层抽象,将复杂的协议编解码和数据传输封装到了一个函数中。
======缺点=====
单一 RPC 无法实现 push,即推送服务。
理由是,RPC 是client 调用 server获取数据,是一个完整的过程,实现不了server调用client。
解决方案:让client 既可以调用server上的RPC服务,反之client本身也成为一个RPC服务让Server来调用。
=====回到题主的问题====
1. Netty只是网络通信框架,目的是让你用最少的代码构建出足够支撑网络通信的功能。
2.完成RPC 需要两个协议: 对象序列化协议 和 调用控制协议
常见例子举例:
1.zeroC ICE,拥有自己的网络通信框架 + ICE 调用控制协议和对象序列化协议,同时也涵盖了服务组件的抽象部署等功能。
2.thrift,有自己的网络通信框架+thrift 对象序列化协议+thrift 调用控制协议
3.probuff,只是 对象序列化协议
4.XMLRPC ,jsonRPC,常见的语境是利用HTTP协议作为调用控制协议,XML 和 JSON 作为对象序列化之后的格式。
5.其他的大概也差不多了。
------------
----
---
通信中的协议是你自己规定的,比如你可以规定说当A向B发送数字1, B就打印hello world, 并返回数字1给A, 如果发送数字2,B就打印hello, guy.并发送数字2给A.
这就是一个简单的RPC示例,实际上natty就是干这个的,只不过它提供一套框架给你,让你可以定义自己的规则,实现B里面的函数。
我们来想一想,当A要把数字1发送给B要怎么办呢,你需要用socket,B是server, A是client, B执行完以后再把1通过socket写回即可。你可以用AUPE书中的例子很容易就构建出来。
问题到这里,应该就结束了,事实上就是这么简单,那为什么需要RPC框架呢?
当你给B发送1或者2就可以区分函数方法,但是你不可能写100个函数打印100个字符,你需要在发送1的时候,再接着发送一个字符串,这样B只要实现一个通用的print函数就够了。
我们继续思考,当你想发送一个数字比如65534给B的时候,我们知道socket是按照字节接受数据的,一个字节最大为255也就是0xff, 如果要发送65534你有两种方法,第一把65534当作5个字符6,5,5,3,4然后让socket接受5个字符。第二,你可以把65534变成二进制0xfffe, 这样你可以先发送一个0xff再发送一个0xfe,也就是先发一个255再发一个254再拼装。
另外在拼装这255和254的时候,我们知道不同体系结构的CPU字节序是不一样的,因此,你需要解决大端小端字节序的问题。否则对于一个32位机器上,65534作为一个int型可能会是0xfffe0000,或者0x0000feff,这取决于你如何发送和打包它。
对于相对复杂的RPC, 我们发送的一个数据包往往既包含字符串又包含数字,这样我们就需要把他们切割开来然后分别解码编码。
这个部分就叫做序列化反序列化,在高级一点的RPC框架中,甚至可以做到把
一个类从A扔给B.用到的还是这个方法,只是把类这个类型也放进去了。
对于脚本语言比如Lua,你甚至可以把编译过后的字节码发给远程,然后在B用Lua虚拟机执行。
所以对于一个完整的RPC框架底层往往是socket搭配序列化反序列化的工作。
问题到这里,一个RPC分析应该也结束了, 实际上要想把一个RPC做稳定了,还有几个问题。
首先,要想让一个RPC能够更高效,往往做到让A可以连续向B发送请求,这就要求在协议解析的时候区分两个包,在TCP分包的时候这里有个问题叫做半包和粘包。
另外B也无需在返回完函数1以后再返回函数2,这就要求在返回的时候,A能够区分开来,这就要求在协议里面加入session.
高效的写法不但在编解码和协议设计理念,还需要在编写socket server时候,尽可能降低阻塞调用,用异步来做,这有一大推开源方案,比如libev.
netty就是一个这样异步的RPC通信框架。
当然,在实际项目中,我们只是需要解决实际问题,完全没必要从头构建,你可以选一个通信协议比如protobuf/JSON/msgpack/thrift等等再找他相关的RPC库使用即可。
当然完全可以自己定制。
一个好的框架不只是解决最基本的问题,它更像是一个生态系统,比如我看到netty还有SSL的部分,DNS部分。
谁能用通俗的语言解释一下什么是 RPC 框架的更多相关文章
- 谁能用通俗的语言解释一下什么是 RPC 框架?
转载自知乎:https://www.zhihu.com/question/25536695 知乎上很多问题的答案还是很好的,R大就经常在上面回答问题 关于RPC你的题目是RPC框架,首先了解什么叫RP ...
- 转载:怎样用通俗的语言解释REST,以及RESTful?
作者:覃超链接:https://www.zhihu.com/question/28557115/answer/48094438来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出 ...
- 用通俗的语言解释restful
实现了REST规范的Web API就叫RESTful API. 简单来说:就是用url定位资源,用http描述来操作资源. web是什么:分布式信息系统为超文本文件和其他对象(资源)提供访问入口. 资 ...
- 用通俗的语言解释 Spring 中的 DI 、IOC 和AOP概念
DI 所谓依赖,从程序的角度看,就是比如A要调用B的方法,那么A就依赖于B,反正A要用到B,则A依赖于B.所谓倒置,你必须理解如果不倒置,会怎么着,因为A必须要有B,才可以调用B,如果不倒置,意思就是 ...
- Spring框架的AOP编程,最通俗的语言解释,易懂易学
第七章:AOP技术 前言: AOP技术是根据动态代理设计模式进行的技术.动态代理技术分jdk动态代理和cglib动态代理 jdk动态代理特点: (1)继承java.lang.reflect.proxy ...
- 【RPC】跨语言-RPC框架
跨语言-RPC框架 跨语言 rpc_百度搜索 (5 条消息)谁能用通俗的语言解释一下什么是 RPC 框架? - 知乎 跨语言RPC框架Hessian.Thrift.Protocol Buffer之间的 ...
- 用通俗的例子解释OAuth和OpenID的区别【原】
什么是OAuth(Wiki) 什么是OpenID(Wiki) 详细的定义可以看wiki,下面举个例子说说我的理解 现在很多网站都可以用第三方的账号登陆,比如,现在我要登录淘宝买东西,而如果我没有淘宝的 ...
- 关于JAVA,特点,历史,编译式的语言&解释式的语言,什么是java?JDK?DOS?一次编译到处运行原理。
1.java语言的特点: 简单的:面向对象的:跨平台(操作系统)的(一次编译,到处运行):高性能的: 2.类名的首字母大写,方法小写: 3.历史: java2(即java),为什么加个2呢?1998年 ...
- RPC 框架通俗解释 转自知乎(洪春涛)
本地过程调用 RPC就是要像调用本地的函数一样去调远程函数.在研究RPC前,我们先看看本地调用是怎么调的.假设我们要调用函数Multiply来计算lvalue * rvalue的结果: 那么在第8行时 ...
随机推荐
- atomikos + druid 连接超时失效
atomikos + druid 连接超时失效,需要多次连接才能成功. 首次连接会报异常: 2018-01-08 16:58:12 DEBUG [com.jpcar.model.dao.jpcar.A ...
- 收集Nginx的json格式日志(五)
一.配置nginx [root@linux-node1 ~]# vim /etc/nginx/nginx.conf #修改日志格式为json格式,并创建一个nginxweb的网站目录 log_form ...
- [CodeForces - 848B] Rooter's Song 思维 找规律
大致题意: 有一个W*H的长方形,有n个人,分别站在X轴或Y轴,并沿直线向对面走,第i个人在ti的时刻出发,如果第i个人与第j个人相撞了 那么则交换两个人的运动方向,直到走到长方形边界停止,问最后每个 ...
- 自然语言处理系列-1.什么是NLP?
常常会听到有人说,自然语言处理(NLP)是人工智能技术(AI)皇冠上的明珠.那么,从这句话上就能够看到,目前我们常常说的NLP其实是AI技术的一个分支,而且是较难的那一个分支. 那么,到底什么是NLP ...
- UVALive - 6912 Prime Switch (状压DP)
题目链接:传送门 [题意]有n个灯,m个开关,灯的编号从1~n,每个开关上有一个质数,这个开关同时控制编号为这个质数的倍数的灯,问最多有多少灯打开. [分析]发现小于根号1000的质数有10个左右,然 ...
- sqlldr 远程数据库
connect username/password@hostname:port/SERVICENAME select sys_context('USERENV','SERVICE_NAME') fro ...
- CSS3组件化之ios版菊花loading
<div class="juhua-loading"> <div class="jh-circle1 jh-circle-ios">&l ...
- SQL注入实验
看到他们黑站感觉很有意思的样子,于是我也玩了一下午,虽然都是些狠狠狠简单的东西,不过还是记录下来啦. 虽然和我现在做的没啥关系,不过,,,挺好 浏览器的“工具”——“internet选项”——“高级” ...
- requests爬取百度音乐
使用requests爬取百度音乐,我想把当前热门歌手的音乐信息爬下来. 首先进行url分析,可以看到: 歌手网页: 薛之谦网页: 可以看到,似乎这些路劲的获取一切都很顺利,然后可以写代码: # -*- ...
- 线性表之顺序表C++实现
线性表之顺序表 一.头文件:SeqList.h //顺序线性表的头文件 #include<iostream> ; //定义顺序表SeqList的模板类 template<class ...