RPC远程过程调用
rpc的理解
- RPC, 英文全名remote procedure call 即远程过程掉调用
- 就是说一个应用部署在A服务器上,想要调用B服务器上应用提供的方法
- 由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据
- RPC就是要像调用本地的函数一样去调用远程函数
RPC中协议的作用
我们知道 RPC 需要将对象序列化成二进制数据,写入本地 Socket 中,然后被网卡发送到网络设备中进行网络传输。但是在传输过程中,RPC 并不会把请求参数的所有二进制数据整体一下子发送到对端机器上,中间可能会拆分成好几个数据包,也可能会合并其他请求的数据包(同一个 TCP 连接上的数据),至于怎么拆分合并,这其中的细节会涉及到系统参数配置和 TCP 窗口大小。对于服务提供方来说,他会从 TCP 通道里面收到很多的二进制数据,那这时候怎么识别出哪些二进制是第一个请求的呢?
所以我们需要对 RPC 传输数据的时候进行“断句”,在应用发送请求的数据包里面加入“句号”,这样接收方应用数据流里面分割出正确的数据,“句号”就相当于是消息的边界,用于标识请求数据的结束位置。于是需要在发送请求的时候定一个边界,在请求收到的时候按照这个设定的边界进行数据分割,避免语义不一致的事情发生,而这个边界语义的表达,就是所谓的协议。
粘包拆包
RPC 通信使用 TCP,TCP 是一个“流”协议。所谓流,就是没有界限的一长串二进制数据。TCP 作为传输层协议,并不了解上层业务数据的具体含义,它会根据 TCP 缓冲区的实际情况进行数据包的划分,所以在业务上认为是一个完整包的,可能会被 TCP 拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的 TCP 拆包和粘包问题。
直接序列化发出去是可以,但是接收方收到了一坨数据包,它不知道一个完整的报文哪里开始、哪里结束,也就没有办法解析了。
粘包拆包的解决方案
由于底层的 TCP 无法理解上层的业务数据,所以在底层是无法保证数据包不被拆分和重组的,这个问题只能通过上层的应用协议栈设计来解决。目前业界主流协议的解决方案如下:
- 消息定长:报文长度固定,例如每个报文的长度固定为 200 字节,如果不够空位补空格,接受方每次拿 200 字节。
- 使用特殊分隔符分割:例如每条报文结束都添加回车换行符作为报文分隔符,接收方读到回车换行符则分割出报文。
- 将消息分为消息头和消息体,消息头包含消息的长度。接收方从消息头拿到消息长度,就知道剩下的报文是多少字节了。
- 更复杂的自定义应用层协议。
与HTTP请求的区别
-
首先,rpc是一个完整的远程调用方案,他通常包括通讯协议和序列化协议
-
其中,通信协议包含http协议,(如gRPC使用HTTP2)、自定义报文的tcp协议(如dubbo)
-
序列化协议包含基于文本编码的xml、json,基于二进制编码的protobuf、hessian等
-
而HTTP只是一个通信协议,不是一个完整的远程控制协议
-
也就是说,HTTP和RPC不是对等的概念,用来比较不合适
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了