RPC实战与核心原理——协议:怎么设计可扩展且向后兼容的协议(笔记)

协议的作用

在网络传输过程中需要采用二进制传输,因此RPC请求在发送到网络中之前,需要把方法调用的请求参数转成二进制;转成二进制后,写入本地 Socket 中,然后被网卡发送到网络设备中。但在传输过程中,RPC 并不会把请求参数的所有二进制数据整体一下子发送到对端机器上,中间可能会拆分成好几个数据包,也可能会合并其他请求的数据包。因此,需要正确区分网络包的起始和终止位置,保证不产生歧义。而协议就是解决上述问题的。

如何设计协议

为什么不适用现成的HTTP协议

(1)相对于 HTTP 的用处,RPC 更多的是负责应用间的通信,所以性能要求相对更。但 HTTP 协议的数据包大小相对请求数据本身要大很多,又需要加入很多无用的内容,比如换行符号、回车符等;
(2)HTTP 协议属于无状态协议,客户端无法对请求和响应进行关联,每次请求都需要重新建立连接,响应完成后再关闭连接。

RPC协议包含的内容

定长协议

(1)首先解决消息边界问题。RPC每次发送请求的大小都是不固定的,协议必须能让接收方正确地读出不定长的内容。可以固定一个长度用来存储整个请求的大小,接收数据之后,先读取固定长度的位置信息,根据读取内容判断协议体大小。
(2)解决序列化类型:RPC支持的序列化类型很多,若对方不知道使用的序列化类型,就无法正确反序列化。因此,需要把序列化方式单独存储起来,类似于解决消息边界问题
(3)在协议头里面,除了会有协议长度序列化方式,还会放一些像协议标示消息 ID消息类型这样的参数,而协议体一般只放请求接口方法请求的业务参数值和一些扩展属性。这样一个完整的 RPC 协议大概就出来了,协议头是由一堆固定长度参数组成,而协议体是根据请求接口和参数构造的,长度属于可变的,具体协议如下图所示:
在这里插入图片描述

可扩展协议

定长协议无法向协议头添加新参数,如果添加将会导致线上兼容性的问题。如果简单的将新添加的参数放到协议头中,将协议头字段增加,将会导致协议体反序列化错误;如果将新添加的参数放在协议体中,每次读取新参数需要先将协议体反序列化,成本高。解决的关键问题在于让协议头支持可扩展,扩展后协议头的长度就不能定长了。因此,整体协议就变成了三部分内容:固定部分、协议头内容、协议体内容前两部分我们还是可以统称为“协议头”,具体协议如下:
在这里插入图片描述

整体设计原则

怎么去设计一个可“升级”的协议。不仅要让我们在扩展新特性的时候能做到向下兼容,而且要尽可能地减少资源损耗,所以我们协议的结构不仅要支持协议体的扩展,还要做到协议头也能扩展。

猜你喜欢

转载自blog.csdn.net/weixin_42094659/article/details/107581157