Thrift 序列化协议浅析

      最后更新:2022-08-02 22:53:51 手机定位技术交流文章

      背景

      Thrift 是 Facebook 开源的一个高性能,轻量级 RPC 服务框架,是一套全栈式的 RPC 解决方案,包含序列化与服务通信能力,并支持跨平台/跨语言。整体架构如图所示:

      Thrift软件堆是明确定义的,每个组件层是松散耦合的,相互连接的,并且可以根据业务场景灵活地结合,如图所示:

      储蓄本身是一个相对大的话题,这篇文章不包括所有内容,只是其中所包含的序列协议。

      协议原理

      Binary 协议

      消息格式

      下面是通过一个例子对二进制消息格式的直观演示。IDL定义如下:

      编码简图

      编码具体内容

      编码含义

      消息头

      • msg_type:消息类型,包含四个类型

        • 呼叫: 客户端消息. 呼叫远程方法,并期望对方发送答复.

        • OneWay:客户端消息。调用远程方法,不期待响应。

        • 答复:服务侧消息。

        • Exception:服务端消息。异常响应。

      • msg_seq_id:消息序号。客户端使用消息序号来处理响应的失序到达,实现请求和响应的匹配。服务端不需要检查该序列号,也不能对序列号有任何的逻辑依赖,只需要响应的时候将其原样返回即可。

      消息体

      消息体分为两个编码模式:

      1. 定长类型 -> T-V 模式,即:字段类型 + 序号 + 字段值

      2. 变长类型 -> T-L-V 模式,即:字段类型 + 序号 + 字段长度 + 字段值

      • field_type: 包括 String 、 I64 、 Struct 、 Stop 等字段类型。 该字段类型有两个功能:

        • 停止嵌入分析的停止类型

        • 非 Stop 类型用于 Skip(Skip 操作是跳过当前字段,会在「常见问题 - 兼容性」进行讲解)

      • fied_id:字段序列,在解码时按序列识别字段

      • len:用于变量类型的字段的长度,例如 String

      • value:字段值

      数据格式

      1. 定长数据类型

      数据类型 类型标识(8 位) 类型大小(单元:字节)
      bool 2 1
      byte 3 1
      double 4 8
      i16 6 2
      i32 8 4
      i64 10 8

      2. 变长数据类型

      数据类型 类型标识(8 位) 类型大小(长度+值)
      string 11 4 + N
      struct 12 嵌入式数据+一个字符停止(0)
      map 13 1 + 1 + 4 + N*(X+Y) 【key 类型 + val 类型 + 长度 + 值】
      set 14 1 + 4 + N [阀型 + 长度 + 值]
      list 15 1 + 4 + N [阀型 + 长度 + 值]

      其他协议

      紧凑协议

      紧凑协议是二进制压缩协议,在大部分字段的编码方式上与 Binary 协议保持一致。区别在于整数类型(包括变量类型的长度)首先采用zigzag编码。实现变量压缩编码,最大化空间节约。

      那么问题是,变形和zigzag是什么?

      varint 编码

      问题解决:固定长度整数类型的绝对值比空间的小时更浪费

      根据统计数据,在RPC通信中传输的整数值大多是小,使用固定长度存储是浪费的。

      例如,如果你编码了i32类型的7,你可以说前面的3个字符被浪费了:

      00000000 00000000 00000000 00000111

      解决办法是将整数类型从固定存储器转换为变量存储器(使用单个存储器,你绝对不需要两个)

      原理并不复杂,就是将整数按 7bit 分段,每个字节的最高位作为标识位,标识后一个字节是否属于该数据。1 代表后面的字节还是属于当前数据,0 代表这是当前数据的最后一个字节。

      以 i32 类型,数值 955 为例,可以看出,由原来的 4 字节压缩到了 2 字节:

      当然,varint 编码同样存在缺陷,那就是存储大数的时候,反而会比 binary 的空间开销更大:本来 4 个字节存下的数可能需要 5 个字节,8 个字节存下的数可能需要 10 个字节。

      zigzag 编码

      解决的问题:绝对值较小的负数经过 varint 编码后空间开销较大 举个

      本文由 在线网速测试 整理编辑,转载请注明出处,原文链接:https://www.wangsu123.cn/news/31352.html

          热门文章

          文章分类