您现在的位置是:首页 >技术交流 >【RPC、WebSocket】网站首页技术交流

【RPC、WebSocket】

小呆鸟_coding 2024-06-17 10:14:48
简介【RPC、WebSocket】

有HTTP协议为什么还要RPC

TCP

  • TCP三个特点:面向连接、可靠、基于字节流。

基于字节流

  • 字节流可以理解为一个双向的通道里流淌的数据,这个数据是二进制数据,简单来说就是一大堆 01 串。纯裸 TCP 收发的这些 01 串之间是没有任何边界的,会导致粘包问题。因此纯裸的TCP是不能直接拿来用的,你需要在这个基础上加入一些自定义的规则,用于区分消息边界。
    在这里插入图片描述

  • 于是我们会把每条要发送的数据都包装一下,比如加入消息头,消息头里写清楚一个完整的包长度是多少,根据这个长度可以继续接收数据,截取出来后它们就是我们真正要传输的消息体。

  • 消息头,还可以放各种东西,比如消息体是否被压缩过和消息体格式之类的,只要上下游都约定好了,互相都认就可以了,这就是所谓的协议。

  • 于是基于 TCP,就衍生了非常多的协议,比如 HTTP 和 RPC。
    在这里插入图片描述

HTTP 和 RPC

  • TCP 是传输层的协议,而基于 TCP 造出来的
  • HTTP 协议(Hyper Text Transfer Protocol),又叫做超文本传输协议 HTTP 和各类 RPC 协议,它们都只是定义了不同消息格式的应用层协议而已。
  • RPC(Remote Procedure Call),又叫做远程过程调用。它本身并不是一个具体的协议,而是一种调用方式。

本地方法调用

res = localFunc(req)

该方法在远端服务器上暴露的一个方法,如果我们还能像调用本地方法那样去调用它,这样就可以屏蔽掉一些网络细节

res = remoteFunc(req)

在这里插入图片描述

那既然有 RPC 了,为什么还要有 HTTP 呢?

  • 电脑上装的各种联网软件,比如 xx管家它们都作为客户端需要跟服务端建立连接收发消息,此时都会用到应用层协议,在这种C/S架构下,它们可以使用自家造的 RPC 协议,因为它只管连自己公司的服务器就 可以了。
  • 但浏览器,不仅需要访问自家公司服务器,还要访问其他公司服务器,因此它们需要有个统一的标准,HTTP 就是那个时代用于统一B/S的协议。
  • 但现在其实已经没分那么清了,B/S 和 C/S 在慢慢融合。很多软件同时支持多端,比如某度云盘,既要支持网页版,还要支持手机端和 PC 端

HTTP 和 RPC 有什么区别

服务发现

  • 向服务器发起请求时,需要知道IP地址和端口号,才能建立连接,这个找到服务对应的 IP 端口的过程,其实就是服务发现
  • HTTP 中,你知道服务的域名,就可以通过 DNS 服务去解析得到它背后的 IP 地址,默认 80 端口。
  • RPC中,会有专门的中间服务去保存服务名和IP信息,比如 Consul 或者 Etcd,想要访问某个服务,就去这些中间服务去获得 IP 和端口信息

底层连接形式

  • HTTP/1.1 协议,其默认在建立底层 TCP 连接之后会一直保持这个连接(Keep Alive),之后的请求和响应都会复用这条连接。(长连接)
  • RPC 协议,也是通过建立 TCP 长链接进行数据交互,但是RPC一般还会建一个连接池,在请求量大的时候,建立多条连接放在池内,要发数据的时候就从池里取一条连接出来,用完放回去,下次再复用

传输内容(最大区别)

  • 基于 TCP 传输的消息,都是消息头 Header消息体 Body
    • Header 是用于标记一些特殊信息,其中最重要的是消息体长度。
    • Body 则是放我们真正需要传输的内容,而这些内容只能是二进制 01 串
    • 但是对于结构体而言,需要通过 Json,Protobuf。把结构体转换为二进制字符串

在这里插入图片描述

  • 像 Header 里的那些信息,其实如果我们约定好头部的第几位是 Content-Type,就不需要每次都真的把"Content-Type"这个字段都传过来,类似的情况其实在 body 的 Json 结构里也特别明显。
  • RPC,因为它定制化程度更高,可以采用体积更小的 Protobuf 或其他序列化协议去保存结构体数据,同时也不需要像 HTTP 那样考虑各种浏览器行为,比如 302 重定向跳转啥的。因此性能也会更好一些
    在这里插入图片描述
    在这里插入图片描述

有HTTP协议为什么还要WebSocket

  • 从 HTTP 协议的角度来看,就是点一下网页上的某个按钮,前端发一次 HTTP请 求,网站返回一次 HTTP 响应。这种由客户端主动请求,服务器被动响应。
  • 玩挂机游戏,就需要服务器主动发消息给客户端。

使用HTTP不断轮询

  • 网页的前端代码里不断定时发 HTTP 请求到服务器,服务器收到请求后给客户端响应消息。
  • 它其实并不是服务器主动发消息到客户端,而是客户端自己不断偷偷请求服务器,只是用户无感知而已。

长轮询

  • HTTP 请求发出后,一般会给服务器留一定的时间做响应,比如 3 秒,规定时间内没返回,就认为是超时。
  • 如果我们的 HTTP 请求将超时设置的很大,比如 30 秒,在这 30 秒内只要服务器收到了扫码请求,就立马返回给客户端网页。如果超时,那就立马发起下一次请求。
    在这里插入图片描述
  • 像这种发起一个请求,在较长时间内等待服务器响应的机制,就是所谓的长训轮机制。我们常用的消息队列 RocketMQ 中,消费者去取数据时,也用到了这种方式。
  • 本质上还是客户端主动去取数据。

WebSocket

  • TCP 连接的两端,同一时间里,双方都可以主动向对方发送数据。这就是所谓的全双工
  • HTTP/1.1,也是基于TCP协议的,但是是半双工
  • HTTP设计之初,就是考虑网页场景,客户端发送请求,服务器响应。根本没想到客户端和服务器都要互相主动发大量数据
  • 对于网页游戏来说,客户端和服务器需要频繁主动发送数据,于是产生基于TCP的新协议。WebSocket。

怎么建立WebSocket连接

  • 一般都是在浏览器上刷的图文,这时候用的是 HTTP 协议,一会打开网页游戏,这时候要切换成WebSocket 协议。
  • 于是浏览器在 TCP 三次握手建立连接之后,都统一使用 HTTP 协议先进行一次通信。
    • 如果此时是普通的 HTTP 请求,那后续双方就还是老样子继续用普通 HTTP 协议进行交互,这点没啥疑问。
    • 如果这时候是想建立 WebSocket 连接,就会在 HTTP 请求里带上一些特殊的header 头
Connection: Upgrade
Upgrade: WebSocket
Sec-WebSocket-Key: T2a6wZlAwhgQNqruZ2YUyg==
   
  • 浏览器想升级协议(Connection: Upgrade),并且想升级成 WebSocket 协议(Upgrade: WebSocket)。同时带上一段随机生成的 base64 码(Sec-WebSocket-Key),发给服务器。
  • 如果服务器正好支持升级成 WebSocket 协议。就会走 WebSocket 握手流程,同时根据客户端生成的 base64 码,用某个公开的算法变成另一段字符串,放在 HTTP 响应的 Sec-WebSocket-Accept 头里,同时带上101状态码,发回给浏览器。
  • 浏览器也用同样的公开算法将base64码转成另一段字符串,如果这段字符串跟服务器传回来的字符串一致,那验证通过。
HTTP/1.1 101 Switching Protocols

Sec-WebSocket-Accept: iBJKv/ALIW2DobfoA4dmr3JHBCY=

Upgrade: WebSocket

Connection: Upgrade

在这里插入图片描述

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。