虾皮二面:既然有 HTTP 协议,为什么还要有 RPC?

      最后更新:2022-08-04 05:14:12 手机定位技术交流文章

      下面是正文。

      我记得我在工作时,第一次接触RPC协议,然后我非常困惑,我使用HTTP协议很好,为什么使用RPC协议?

      于是就到网上去搜。

      许多解释似乎非常正式,我相信所有平台的人都见过它们,解释,而不是表面上解释,使用一个我们不知道的概念来解释另一个我们不知道的概念,知道的人不需要看,不知道的人看或者不知道。

      这种看了,又好像没看的感觉,云里雾里的很难受,我懂。

      为了避免强烈的丑闻厌倦感,我们今天将尝试一种不同的讲话方式。

      从 TCP 聊起

      作为一个程序员,假设我们需要向A计算机上的进程发送数据,然后向B计算机上的进程发送数据,我们通常会用代码中的插座程序。

      这时候,我们可以选择TCP或UDP。TCP 可靠,UDP 不可靠。除非这是神级程序员(QQ早期使用了很多UDP),否则,只是有点可靠性要求,普通人通常没有选择TCP的头脑。

      类似下面这样。

      其中SOCK_STREAM,是指使用字节流传输数据,说白了就是TCP 协议。

      在定义了 socket 之后,我们就可以愉快的对这个 socket 进行操作,比如用bind()使用绑定IP端口connect()发起建连。

      握手建立连接流程

      连接成立后,我们可以使用send()发送数据,recv()接收数据。

      只有这样裸露的TCP连接才能接收和发送数据,不是吗?

      不,那会是个问题。

      使用裸体TCP有什么问题?

      TCP具有三个特点:面向连接,可靠,和基于字节。

      这些三个特征的确很好地总结, 这些八段我们没有支持.

      每个特征都可以在一个文章中讨论,今天我们需要集中讨论的是基于这个节点流。

      字节流可以理解为一个双向的通道里流淌的二进制数据,也就是01 串。纯裸 TCP 收发的这些 01 串之间是没有任何边界的,你根本不知道到哪个地方才算一条完整消息。

      正因为这个没有任何边界的特点,所以当我们选择使用 TCP 发送"夏洛"和"特烦恼"的时候,接收端收到的就是"夏洛特烦恼",这时候接收端没发区分你是想要表达"夏洛"+"特烦恼"还是"夏洛特"+"烦恼"。

      这就是所谓的粘贴问题,我曾经写过一篇特别的文章。

      说这个的目的是为了告诉大家,纯裸 TCP 是不能直接拿来用的,你需要在这个基础上加入一些自定义的规则,用于区分消息边界。

      因此,我们将所有我们想要发送的数据包起来,比如添加一个消息头条,详细说明一个完整的包的长度,根据这个长度数据可以继续接收,然后这些数据就是我们真正想要发送的实体。

      这里头条提到头条,你可以设置诸如消息体是否压缩和消息体的格式等等,只要所有事情都商定上下,并且每个人都认出对方,这就是所谓的协议。

      每个使用TCP的项目可能定义一套类似的协议分析标准,它们可能不同,但原则是相似的。

      许多协议, 例如HTTP和RPC, 都来自TCP.

      HTTP和RPC

      RPC实际上是一种呼叫方式

      让我们回顾一下网络的层次结构。

      TCP 是传输层的协议,而基于 TCP 造出来的 HTTP 和各类 RPC 协议,它们都只是定义了不同消息格式的应用层协议而已。

      HTTP(HyperTextTransferProtocol)协议又叫做超文本传输协议。我们用的比较多,平时上网在浏览器上敲个网址就能访问网页,这里用到的就是 HTTP 协议。

      RPC(RemoteProcedureCall)也被称为远程过程调用,不是特定协议,而是调用的方式。

      例如,我们通常称之为这样一种地方方法。

      如果现在不是本地方法,则是一个由远程服务器公开的方法remoteFunc,如果我们还能像调用本地方法那样去调用它,这样就可以屏蔽掉一些网络细节,用起来更方便,岂不美哉?

      基于这个想法,洋基开发了非常广泛的RPC协议,例如更著名的gRPCthrift

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

      现在我们回到文章的主题。

      既然有RPC,为什么HTTP呢?

      事实上,TCP是1970年代出现的协议,HTTP直到1990年代才流行起来。 而且,直接使用裸体TCP存在问题。 你可以想象有多少自定义的协议在这些年之间存在,这就是80年代出现的RPC

      所以我们不应该问为什么有RPC,因为有HTTP协议,而是问为什么有RPC和HTTP协议?

      现在所有的网络软件都安装在计算机上,比如 xx 管家,xx 卫士,它们都作为客户端(Client) 需要跟服务端(Server) 建立连接收发消息,当前正在使用应用程序层协议,在这个客户端/服务器(C/S)架构下,他们可以使用自己的RPC协议,没关系,因为它只管理自己的服务器。

      但有个软件不同,浏览器(Browser) ,Chrome或IE,他们不仅需要能够访问自己的公司服务器,你还需要访问其他公司的网站服务器,所以他们需要统一的标准,不然大家没法交流。于是,HTTP 就是那个时代用于统一Browser/Server (B/S)的协议。

      就是,几年前,HTTP主要用于B/S架构,RPC更用于C/S架构。但现在情况并不那么清楚,B/S和C/S慢慢融合。许多软件同时支持多个目的,比如某度云盘,既要支持网页版,它还支持移动电话和个人电脑,如果所有通信协议使用HTTP,这个服务器用同样的组件就足够了。RPC开始在幕后留下,一般用于公司内部集团,不同微型服务之间的通信。

      那这么说的话,都用 HTTP 得了,还用什么 RPC?

      好像我们回到文章的开头了,那从它们之间的差异开始。

      HTTP和RPC 有什么区别

      让我们看看RPC和HTTP之间的一些明显的区别。

      服务发现

      为启动服务器的请求,您必须首先建立连接,建立连接的前提是您知道IP地址和端口。 为该服务找到相应的IP端口的过程实际上是服务发现。

      在HTTP中,您知道该服务的域名,并且可以通过DNS服务,默认的80端口来分析其背后的IP地址。

      而RPC的话,就有些区别,通常有一个专门的中间服务存储服务名称和IP信息,例如,领事,Etcd,Nacos,ZooKeeper,甚至雷迪斯。想要访问某个服务,到这些中间服务获取IP和港口信息。因为DNS也是一个服务发现,所以还有基于DNS的组件来进行服务发现,例如, CoreDNS。

      可以看出,服务发现这幅作品,两者略有不同,但没有太多可以分开。

      底层连接形式

      例如,Mainstream HTTP1.Protocol 1默认地在建立基线TCP连接后维持此连接(保持生命),随后的请求和响应将复制此连接。

      而RPC协议,类似HTTP,通过建立与数据交互的TCP长链路,但不同的地方在于,RPC协议通常也重建一个连接池,在请求量大的时候,在池中建立多个连接,当你想发送数据时,你从池中取出一个连接,用完放回去,下次再复用,可以说非常环保。

      由于连接池有利于提升网络请求性能,所以不少编程语言的网络库里都会给 HTTP 加个连接池,比如 Go 就是这么干的。

      可以看出,这幅作品并没有太大的区别,所以这不是关键。

      传输的内容

      基于 TCP 传输的消息,说到底,无非都是消息头 Header 和消息体 Body。

      头条用于标记某些特殊信息, 最重要的是消息的长度.

      身体是我们真正需要传播的,这些内容只能是二进制01字符串,毕竟, 电脑只知道这个游戏.所以TCP传输字符串和数字并不是问题,因为字符串可以转换为代码并成为01字符串,数字本身也可以直接转换为二进制。但结构体呢,我们还得找出一种把它转换成二进制01字符串的方法。许多这样的计划已经实施,比如JSON,Protocol Buffers (Protobuf)。

      将结构转换成二进制序列的过程称为序列化,而将二进制序列重构成结构的过程则称为逆序列化。

      对于主流HTTP1.1,虽然现在它被称为超文本协议,支持音频视频,但是HTTP的设计最初是用来显示网页文本的,因此它传输的内容主要是一个字符串。头条和身体是相同的。在肉体中,它使用JSON来序列结构数据。

      我们可以拍一张照片,看看它。

      你可以看到,这里面有很多冗余,而且很吵闹。 最明显的是,像头条的信息一样,如果我们同意一个好的头条,第一个数字就是Content-Type你不必经常这么做Content-Type这个领域被传递,并且类似的情况实际上在Body的JSON结构中尤为明显。

      而 RPC,由于高度的定制,一个较小的Protobuf或其他序列化协议可以用于存储结构数据。也不需要考虑HTTP等浏览器的行为,例如, 302 是转向跳跃的。结果会更好,在公司内部的微服务中也放弃了HTTP,选择使用RPC的主要原因。

      HTTP原理

      RPC原理

      当然,上面提到的HTTP具体指的是当前主流HTTP1.1,HTTP2许多改进已经基于前者,所以性能可能比许多RPC协议更好,甚至gRPC底层都直接用的HTTP2

      那么问题又来了。

      为什么现在还有 HTTP2 的 RPC 协议?

      这是因为HTTP2于2015年发布,当时公司内部的许多RPC协议已经运行多年,而且由于历史原因,它们一般不需要被更换。

      总结

      • 纯裸的TCP可以传输数据,但它是一个无边的数据流,上层需要定义消息格式来定义消息边界。 因此,有各种协议,HTTP和RPC协议都是在TCP上定义的应用程序层协议。

      • RPC基本上不是一项协议,而是一种调用方式,以及gRPC和Thrift等具体的实现,才是协议,它们是实现RPC调用协议的.其目的是使程序员能够调用远程服务方法,如调用本地方法。同时,RPC有多种实现方法,不一定基于TCP协议。

      • 从发展历史来说,HTTP主要用于B/S架构,RPC更用于C/S架构。但现在情况并不那么清楚,B/S和C/S慢慢融合。许多软件同时支持多个目的,所以外部一般使用HTTP协议,RPC协议用于内部集群的微服务之间的通信。

      • RPC实际上比HTTP更早出现,比当前主流HTTP更早出现。 性能更好,所以大多数公司仍然使用RPC。

      • HTTP2.0在HTTP1中。 基于1的优化,性能可能比许多RPC协议更好,但它不太可能取代RPC,因为它只是在近几年才发布。

        如果这篇文章对你有帮助,别忘了给我三个链接,赞扬,翻译,评论,

        学习更多Java知识和技能,集中学习Java教程、源代码、安装包和最新的工厂面试信息等。

        咱们下期见。

        收藏就像一张空白的支票, 赞美是事实.


      本文由 在线网速测试 整理编辑,转载请注明出处,原文链接:https://www.wangsu123.cn/news/31491.html

          热门文章

          文章分类