RPC概述 | 青训营笔记

103 阅读6分钟

这是我参与「第五届青训营 」笔记创作活动的第3天。

学习 hertz 时,对于 RPC 不理解,查看文章后,将其与 HTTP 做类比与区分。

背景

当业务的需求越来越大时,往往需要引入微服务的架构:将单体服务拆分为多个独立的小服务,这有利于代码的解耦,更容易实现对某个小服务的维护。当有些服务需要调用其他服务的方法时,不同服务器之间就需要通信,而采用什么通信方式即需要引入 TCP、HTTP、RPC 的概念。

想象把需要调用方法的服务器当做浏览器客户端,服务的提供方作为服务端,其实就可以使用 HTTP 协议实现通信,甚至可以使用 TCP 直接进行通信,但是为啥使用 RPC ,以下将说明。

TCP 传输数据

TCP 协议是在传输层通过字节流传输信息的,其面向连接,安全可靠。赤裸的TCP连接其实已经具备了传输数据的功能,但是其在传输字节流的过程中并不知道何时结束,他是没有边界的,所以需要使用更上一层的协议进行封装 TCP 传递的数据,即消息头和消息体。

TCP传输数据格式

根据不同的封装形式,衍生除了很多应用层的协议,如 HTTP 和 RPC 等

HTTP和RPC

基本介绍

这两者最大的相同点是使用的都是基于 TCP 协议的应用层协议,他们的最根本的区别其实就是定义的消息格式不一样。

HTTP 为超文本传输语言,主要用于浏览器与服务器之间的通信。

RPC 为远程过程调用。假设把服务调用方和提供方融为一体,也就是所谓的单体服务,当调用某一个服务的某一个服务时,类似于在调用本地的一个方法,但是这种理想情况是不太可能的。若提供方把自己的方法暴露出去,并且调用方可以直接使用,省去了很多网络的细节,这样远程调用就和本地调用过程差不多了。

RPC协议底层使用TCP,但实际上它们不一定非得使用TCP,改用UDP或者HTTP,其实也可以做到类似的功能。

相互的关系

从时间上看,TCP70年代出来的协议,而HTTP90年代才开始流行的。而直接使用裸TCP会有问题,可想而知,这中间这么多年有多少自定义的协议,而这里面就有80年代出来的RPC

一开始计算机上的软件多采用 C/S 结构体系,软件的生产商使用自己家的远程服务即可,通过自家的 RPC 即可调用自家的服务。但是后面浏览器的出现,很多应用使用的是 B/S 结构,此时浏览器访问的不仅仅是一家的服务器,而是要访问多家服务器,如果没有一个用以的标准,则几乎无法进行通信了,所以 HTTP 开始盛行。 也就是说在多年以前,HTTP主要用于b/s架构,而RPC更多用于c/s架构。但现在其实已经没分那么清了,b/s和c/s在慢慢融合。 很多软件同时支持多端,比如某度云盘,既要支持网页版,还要支持手机端和pc端,如果通信协议都用HTTP的话,那服务器只用同一套就够了。而RPC就开始退居幕后,一般用于公司内部集群里,各个微服务之间的通讯。

那么回到原始的问题,为什么在微服务之间的通讯使用的是 RPC 而不是 HTTP 呢,此时需要说明他们之间的区别。

不同点

1. 服务发现

如果需要调用某一个服务的某一个方法,首先需要建立连接,即找到IP地址以及服务所在端口号,这个过程即为服务发现。

  • HTTP:当知道服务的域名,就可以通过DNS服务去解析得到它背后的IP地址,默认80端口。
  • RPC:一般会使用专门的中间服务来存储服务名及其IP地址和端口号,比如etcd或者consul,也可以是Redis,甚至可以使用dns的方式,如CoreDNS 该区别其实没有太大的影响。

2. 底层连接形式

  • HTTP:以主流的HTTP1.1协议为例,其默认在建立底层TCP连接之后会一直保持这个连接(keep alive),之后的请求和响应都会复用这条连接。
  • RPC:与 HTTP 类似,也是通过建立TCP长链接进行数据交互,但RPC协议还会建立一个连接池,当请求量大的时候,建立多条连接放到连接池中,相当于预分配了资源,当需要传输数据时取出一条数据,使用完毕后再放回去,提高了性能与效率。

3. 传输内容

两个协议都是基于TCP传输数据的,实质上传输的都是消息头 header 和消息体 body。 对于应用层从来说,数据需要直观的解释,但是对于计算机而言,在传输这些数据的过程中只能是 01 序列,字符串或者数字可以直接转化为 01 序列。而结构体不能直接被转化为 01 序列,需要进行序列化才能变为 01 序列,目前的方案有 json、protobuf、thrift等 在微服务场景下,这些被称为 IDL (接口定义语言)。以下为各IDL的性能对比

IDL编解码体积反射RPC接口Schema可读性
PB支持不支持支持需解码
Thrift不支持支持支持需解码
JSON支持不支持-
  • HTTP1.1中,其传输的内容主要由字符串组成,body 使用 json 来序列化结构体数据。但是在 HTTP 传输的信息中,其实存在很多冗余信息,比如 content-type 字段,如果约定某几个字节为 content-type 的值,则不需要传输 "content-type" 这几个字符。
  • RPC 的定制化很高,可以使用 protobuf 这种体积更小的序列化协议保存数据传输,这样相对于 HTTP 来说,首先数据格式变得简单,且有些字段不需要传输,数据的体积变小了,传输起来就变得更快,所以 RPC 被选为内部服务器之间的传输协议。

HTTP 2.0 针对 1.x 版本做了很多优化,甚至有些 RPC 框架底层直接使用该协议,性能也比较好。但是由于一些历史原因,现在流行的仍然是 HTTP1.x 和 RPC

Reference