简单来说:可以分为编解码层、协议层、网络通信层
- 广义编解码层:包括
Service.client\Processor、read\write、TProtocal - 狭义编解码层:
TProtocal Code部分是不在框架内的- IDL:
Service.client\Processor+read\write- 是RPC框架的约束
- client和server依赖同一份IDL文件
并通过工具将IDL文件转换成不同语言的代码
1.1 编解码层
1.1.1 数据格式
-
语言特定编码格式:许多编程语言都内建了将内存对象编码为字节序列的支持
这种编码形式好处是非常方便,可以用很少的额外代码实现内存对象的保存与恢复,这类编码通常与特定的编程语言深度绑定,其他语言很难读取这种数据。如果以这类编码存储或传输数据,那你就和这门语言绑死在一起了。安全和兼容性也是问题。 -
文本格式:JSON、XML、CSV等文本格式,具有人类可读性
文本格式具有人类可读性,数字的编码多有歧义之处,比如XML和CSV不能区分数字和字符串。JSON虽然区分字符串和数字,但是不区分整数和浮点数,而且不能指定精度,处理大量数据时,这个问题更严重了。
没有强制模型约束,实际操作中往往只能采用文档方式来进行约定,这可能会给调试带来一些不便。由于JSON在一些语言中的序列化和反序列化需要采用反射机制,所以在性能比较差。 -
二进制编码:具备跨语言和高性能等优点
常见有Thrift的BinaryProtocol,s.Protobuf等,实现可以有很多种, TLV 编码和 Varint 编码,本质上是转换为二进制流
1.1.2 二进制编码
- TLV编码:
结构:
Tag:标签,可以理解为类型Lenght: 长度Value:值,Value 也可以是个TLV结构
TLV编码有额外字节的开销:比如field tag和Length
1.1.3 编码选型
-
通用性: 通用性有两个层面的意义:
- 技术层面
序列化协议是否支持跨平台、跨语言。如果不支持,在技术层面上的通用性就大大降低了。 - 流行程度
序列化和反序列化需要多方参与,很少人使用的协议往往意味着昂贵的学习成本;另一方面,流行度低的协议,往往缺乏稳定而成熟的跨语言、跨平台的公共包。
- 技术层面
-
兼容性:
在移动互联时代,业务系统需求的更新周期变得更快,新的需求不断通现,而老的系统还是需要继续维护。
如果序列化协议具有良好的可扩展性,支持自动增加新的业务字段,而不影响老的服务,这将大大提供系统的灵活度 -
性能:
- 空间开销(Verbosity)
序列化需要在原有的数据上加上描述字段,以为反序列化解析之用。如果序列化过程引入的额外开销过高,可能会导致过大的网络,磁盘等各方面的压力。对于海量分布式存储系统,数据量往往以TB为单位,巨大的的额外空间开销意味着高昂的成本。 - 时间开销(Complexity)
复杂的序列化协议会导致较长的解析时间,这可能会使得序列化和反序列化阶段成为整个系统的瓶颈
- 空间开销(Verbosity)
1.2 协议层
协议是双方确定的交流语义。
比如:我们设计一个字符传输的协议,他允许客户端发送一个字符串。这个协议很简单,首先发送4字节的消息总长度,然后再发送1字节的的字符集charset长度,接下来就是消息的payload,字符集名称和字符串正文。
特殊结束符协议
- 过于简单,对于一个协议单元必须要全部读完才能够进行处理,除此之外,必须要防止用户传输的数据不能同结束符相同,否则就会出现紊乱
- HTTP 协议头就是以回车(CR)加换行(LF)符号序列结尾。
变长协议:
- 一般是自定义协议,由
header和payload组成,会以定长加不定长的部分组成,其中定长的部分需要描述不定长的内容长度,使用比较广泛。
协议构造
LENGTH字段:
32bits,包括数据包剩余部分的字节大小,不包含LENGTH自身长度HEADER MAGIC字段:
16bits,值为:Ox1000,用于标识协议版本信息,协议解析的时候可以快速校验FLAGS字段:
16bits,为预留字段,暂未使用,默认值为 0x0000SEQUENCENUMBER字段:
32bits,表示数据包的seqId,可用于多路复用,最好确保单个连接内递增HEADER SIZE字段:
16bits,等于头部长度字节数/4,头部长度计算从第14个字节开始计算,一直到PAYLOAD前 (备注:header的最大长度为64K)PROTOCOL ID字段:
uint8编码,取值有:~、ProtocollDBinary = 0、ProtocollDCompact = 2NUM TRANSFORMS字段:
uint8编码,表示TRANSFORM个数TRANSFORM ID字段:
uint8编码,表示压缩方式zliborsnappyINFO ID字段:
uint8 编码,用于传递一些定制的 meta 信息PAYLOAD消息内容
1.3 网络通信层
未完待续……