小林计网笔记-3.8既然有HTTP协议,为什么还要有RPC?

3.8既然有HTTP协议,为什么还要有RPC?

从TCP聊起

假如我们需要在A电脑的进程发一段数据到B电脑的进程,我们一般会在代码里使用Socket进行编程。
选择TCP还是UDP?TCP可靠,UDP不可靠。

fd=socket(AF_INET,SOCK_STREAM,0);

其中,SOCK_STREAM,是指使用字节流传输数据,即选用TCP协议。
在定义Socket之后,我们可以对这个Socket进行操作,比如bind()绑定IP端口,用connect()发起建连。
在这里插入图片描述

在连接建立之后,我们可以使用send()发送数据,recv()接收数据。
光这一一个纯裸的TCP连接,就可以做到收发数据了,那是不是就够了?
不行,这么用会用问题。

使用纯裸TCP会有什么问题

TCP有三个特点:面向连接,可靠、基于字节流
在这里插入图片描述
字节流可以理解为一个双向的通道里流淌的数据,这个数据其实就是我们常说的二进制数据,简单来说是一大堆01串。纯裸TCP收发的这些01串之间是没有任何边界的,你根本不知道哪个地方才算一条完整消息。
在这里插入图片描述
正因为这个没有任何边界的特点,所以当我们选择使用TCP发送”夏洛“和”特烦恼“的时候,接收端收到的就是”夏洛特烦恼“,这时候接收端没法区分你是想要表达”夏洛“+”特烦恼“还是”夏洛“+”特烦恼“,这就是所谓的粘包问题
在这里插入图片描述

由此可知,纯裸TCP是不能直接拿来用的,需要在这个基础上加入一些自定义的规则,用来区分消息边界
我们会把每条要发送的数据都包装一下,比如加入消息头,消息头里写清楚一个完整的包长度是多少,根据这个长度可以继续收接数据,截取出来后它们就是我们真正要传输的消息体
在这里插入图片描述
消息头里还可以放各种东西,比如消息体是否被压缩过和消息体格式之类的,只要上下游都约定好了,互相都认得就可以了,这就是所谓的协议
每个使用TCP的项目都可能定义一套类似这样的协议解析标准,它们可能有区别,但原理都类似。
于是基于TCP,就衍生了非常多的协议,比如HTTP和RPC。

HTTP和RPC

在这里插入图片描述
TCP是传输层的协议,而基于TCP造出来的HTTP和各类RPC协议,它们都只是定义了不同消息格式的应用层协议而已。
HTTP协议(Hyper Text Transfer Protocol,超文本传输协议)。我们平时在浏览器上敲个网址就能访问网页,这里用到的就是HTTP协议。
在这里插入图片描述
RPC(Remote Procedure Call,远程过程调用)。它本身并不是一个具体的协议,而是一种调用方式
举个栗子,我们平时调用一个本地方法:

res=localFun(req);

如果现在这不是个本地方法,而是个远端服务器暴露出来的一个方法remoteFunc,如果我们还能像调用本地方法一样调用它,这样就可以屏蔽一些网络细节,用起来更方便。

res=remoteFunc(req);

在这里插入图片描述
基于这个思路,大佬们造出了非常多款式的RPC协议,比如比较出名的gRPC,thrift。
虽然大部分RPC协议底层使用TCP,但实际上它们不一定非得用TCP,改用UDP或HTTP,其实也可以做到类似的功能。
在这里插入图片描述
TCP是70年代出来的协议,而HTTP是90年代才开始流行的。而直接使用裸TCP会有问题,可想而知,这中间这么多年有多少自定义的协议,而这里就有80年代出来的RPC。
现在电脑上装的各自联网软件,比如**管家,–卫士,它们都作为客户端(Client)需要跟服务器(Server)建立连接收发信息,此时都会用到应用层协议,在这种Client/Server(C/S)架构下,它们可以使用自家造的RPC协议,因为它只管连自己公司的服务器就ok.
但是有个软件不同,浏览器(Browser),不管是Chrome还是IE,它们不仅要能访问自家公司的服务器(Server),还需要访问其他公司的网站服务器,因此它们需要有个统一的标准,不然大家没法交流。于是,HTTP就是那个时代用于统一Browser/Server(B/S)的协议。
多年以前,HTTP主要用于B/S架构,而RPC更多用于C/S架构。但是现在其实已经没有分那么清了,B/S和C/S在慢慢融合。很多软件同时支持多端,比如百度云盘,既要支持网页版,还要支持手机端和PC端,如果通信协议都用HTTP的话,服务器只用一套就够了。而RPC就开始退居幕后,一般用于公司内部集群,各个为服务器之间的通讯。
都用HTTP得了,还用什么RPC?

HTTP和RPC有什么区别

服务发现

要向某个服务器发起请求,你得先建立连接,而建立连接的前提是,你得知道IP地址和端口,这个找到服务对应的IP端口的过程,其实就是服务发现
HTTP中,你知道服务的域名,就可以通过DNS服务去解析得到它背后的IP地址,默认80端口。
RPC的话,就有些区别,一般会有专门的中间服务保存服务名和IP信息,比如Consul或者Etcd,甚至是Redis。想要访问某个服务,就去这些中间服务去获得IP和端口信息。由于DNS也是服务发现的一种,所以也有基于DNS去做服务发现的组件,比如CoreDNS.
可以看出服务发现这一块,两者是有些区别,但不太能分高低。

底层连接形式

以主流的HTTP/1.1协议为例,其默认在建立底层TCP连接之后会一直保持这个连接==(Keep Alive),之后的请求和响应都会复用这条连接。
而RPC协议,也跟HTTP类似,也是通过建立TCP长连接进行数据交互,但不同的地方在于,RPC协议一般还会再建个
连接池==,在请求量大的时候,建立多条连接放在池内,要发数据的时候就从池里取一条连接出来,用完放回去,下次再复用
在这里插入图片描述
由于连接池有利于提升网络请求性能,所以不少编程语言的网络库都会给HTTP加个连接池,比如Go就是这么干的。
可以看出这一块两个也没太大区别,所以也不是关键。

传输的内容

基于TCP传输的消息,消息头Header和消息体Body
Header是用于标记一些特殊信息,其中最重要的是消息体长度
Body则是放我们真正需要传输的内容,而这些内容只能是二进制01串。所以TCP传字符串和数字都问题不大,因为字符串可以转成编码再变成01串,而数字本身也能直接转成二进制。但结构体呢,我们得想个办法将它也转成二进制01串,这样的方案现在也有很多现成的,比如Json,Protobuf.
将结构体转成二进制数组的过程就叫序列化,反过来讲二进制数组复原成原结构体的过程叫反序列化
在这里插入图片描述

对于主流的HTTP/1.1,虽然它现在叫超文本协议,支持音频视频,但是HTTP设计初是用于做网页文本展示的,所以它传的内容以字符串为主。Header和Body都是如此。在Body这块,它使用Json来序列化结构体数据。
在这里插入图片描述
可以看出这里面的内容非常的冗余,显得非常啰嗦。最明显的,像Header里的那些信息,其实如果我们约定好头部的第几位是Content-Type,就不需要每次都真的把“Content-Type”这个字段都传过来,类似的情况其实在body的Json结构体也特别明显。
而RPC,因为它定制化程度更高,可以采用体积更小的Protobuf或者其他序列化协议去保存结构体数据,同时也不需要像HTTP那样考虑各种浏览器行为,比如302重定向跳转啥的。因此性能更好一些,这也是在公司内部微服务器中抛弃HTTP,选择使用RPC的最主要原因。
在这里插入图片描述
在这里插入图片描述
上面说的HTTP,特指现在主流使用的HTTP/1.1,HTTP/2在前者的基础上做了很多改进,所以性能可能比很多RPC协议还要好,甚至gRPC底层都直接用的HTTP/2
为什么已经有了HTTP/2,还要有RPC?
这是由于HTTP/2是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/1.1性能要好,所以大部分公司内部都还在使用RPC。
  • HTTP/2在HTTP/1.1的基础上做了优化,性能可能比很多RPC协议都要好,但由于是这几年才出来的,所以不太可能取代RPC。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值