RPC协议
需要自定义通信协议,RPC负责应用间的通信,所以性能要求相对较高。以HTTP协议为例,HTTP协议的数据包大小相对请求数据本身要大很多,又要加入很多没用的内容,例如换行符号、回车符号等。还有一个原因是HTTP属于无状态协议,客户端无法对请求合响应进行关联,每次请求都需要重新建立连接,响应完成之后再关闭俩姐。因此对于要求高性能的RPC来说,HTTP协议基本很难满足,RPC需要更加紧凑的私有协议。
How to design?
1、不定长协议
每次请求数据包的大小都是不固定的,然而协议必须能让接收方正确读出不定长的内容。因此需要在协议里面存放整个数据包的大小,这样在接收到数据的时候,先读取固定长的的位置里面的值,值的大小代表着整个协议体的长度,接着在根据值的大小来读取协议体的数据,因此整个不定长的协议可以设计成:协议长度+协议体
2、定长协议
不定长协议只是能够实现正确区分数据包的效果。在RPC里面功能还远远不够。因为服务提供方不知道调用者是使用那种序列化方式生成数据,如果服务提供方不知道怎么反序列化数据的话则无法把二进制数据反序列化成对象,服务提供方无法拿到正确的数据了。
因此我们还需要在协议里面使用固定长的来存放一些参数,通常称之为”协议头“,这样整个协议可以拆分成两部分:协议头+协议体
一般协议头里面还有像一些参数,如下:
位数 | 0-15 | 16-47 | 48-63 | 64-71 | 72-79 | 80-87 |
---|---|---|---|---|---|---|
0 | 魔术位 | 整体长度 | 消息ID | 协议版本 | 消息类型 | 序列化方式 |
协议体 |
0-87 共88位是固定长度存放指定的内容,是剩下的便是协议体的内容
3、可扩展的协议
上面的定长协议是,协议头固定了,不再添加新的参数了。如果需要添加参数则会导致线上的兼容问题。所以我们还需要加入扩展属性,来存放额外/自定义的信息。
位数 | 0-15 | 16-47 | 48-63 | 64-71 | 72-79 | 80-87 |
---|---|---|---|---|---|---|
0 | 魔术位 | 整体长度 | 头长度 | 协议版本 | 消息类型 | 序列化方式 |
88-103 | 消息ID | |||||
不固定 | 协议头扩展字段 | |||||
协议体 |
这样协议便分成了三部分:固定部分+协议头内容+协议体内容。前两部分和起来就是协议头。
小总结
设计一个协议并不难,难的是怎么设计一个可扩展、可升级的协议。要让协议不仅能向下兼容,还要尽可能地减少资源损耗。