1.介绍
RPC(Remote Procedure Call,远程过程调用)是一个计算机通信协议,此协议允许进程间远程通信。简单来说,当机器 A 上的进程调用机器 B 上的进程时,A 上的调用进程被挂起,而 B 上的被调用进程开始执行。调用方可以通过参数将信息传送给被调用方,然后可以通过被调用方传回的结果得到返回。RPC 框架屏蔽了底层传输方式(TCP/UDP)、序列化和反序列化(XML/JSON/二进制)等内容,使用框架只需要知道被调用者的地址和接口就可以了,无须额外地为这些底层内部编程。
协议是 RPC 的核心,它规范了数据在网络中的传输内容和格式。除必须的请求、响应数据外,通常还会包含额外控制数据,如单次请求的序列化方式、超时时间、压缩方式和鉴权信息等。
协议的内容包含三部分:
- 数据交换格式: 定义 RPC 的请求和响应对象在网络传输中的字节流内容,也叫作序列化方式;
- 协议结构: 定义包含字段列表和各字段语义以及不同字段的排列方式;
- 协议通过定义规则、格式和语义来约定数据如何在网络间传输。一次成功的 RPC 需要通信的两端都能够按照协议约定进行网络字节流的读写和对象转换。如果两端对使用的协议不能达成一致,就会出现鸡同鸭讲,无法满足远程通信的需求。
RPC 协议的设计需要考虑以下内容:
- 通用性: 统一的二进制格式,跨语言、跨平台、多传输层协议支持(就是说udp和tcp等传输层协议都支持?)(跨语言是什么意思?比如Java和C++之间?)
- 扩展性: 协议增加字段、升级、支持用户扩展和附加业务元数据
- 性能:As fast as it can be
- 穿透性:能够被各种终端设备识别和转发:网关、代理服务器等。通用性和高性能通常无法同时达到,需要协议设计者进行一定的取舍。(比如说有http伪装)
2.gRPC
Google 选择将 gRPC 直接定义在 HTTP/2 协议之上:
- 基于 HTTP2 的协议足够简单,用户学习成本低,天然有 server push/ 多路复用 / 流量控制能力
- 基于 Protobuf 的多语言跨平台二进制兼容能力,提供强大的统一跨语言能力
- 基于协议本身的生态比较丰富,k8s/etcd 等组件的天然支持协议,云原生的事实协议标准
问题:
- 对服务治理的支持比较基础,更偏向于基础的 RPC 功能,协议层缺少必要的统一定义,对于用户而言直接用起来并不容易。
- 强绑定 protobuf 的序列化方式,需要较高的学习成本和改造成本,对于现有的偏单语言的用户而言,迁移成本不可忽视
3.Thrift
- 最上层用户自行实现的业务逻辑代码
- 第二层,thrift编译自动生成的代码,主要用于结构化数据的解析,发送和接收。TServer主要任务是高效的接收客户端的请求,并将请求转发给processor处理。processor负责对客户端的请求作出响应,包括RPC请求转发,调用参数解析和用户逻辑调用,返回值写回等处理。
- TProtocol是用于数据类型的解析,将结构化数据转化为字节流给TTransport进行传输。
- TTransport是与底层传输密切相关的传输层,负责以字节流的方式接收和发送消息体,不关注是什么数据类型。
- 底层I/O负责实际的数据传输,包括socket,文件和压缩数据流等。