比 Json 还牛的 Protobuf 的编码须知(.proto文件该如何编写)(二)

202 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情

未知字段

未知字段是解析结构良好的 protocol buffer 已序列化数据中的未识别字段的表示方式。例如,当旧程序解析带有新字段的数据时,这些新字段就会成为旧程序的未知字段。

本来,proto3 在解析消息时总是会丢弃未知字段,但在 3.5 版本中重新引入了对未知字段的保留机制以用来兼容 proto2 的行为。在 3.5 或更高版本中,未知字段在解析时会被保留同时也会包含在序列化结果中。

消息类型的更新

如果现有的消息类型不再满足您的所有需求——例如,需要扩展一个字段——同时还要继续使用已有代码,别慌! 在不破坏任何现有代码的情况下更新消息类型非常简单。仅仅遵循如下规则即可:

  • 不要修改任何已有字段的字段编号
  • 若是添加新字段,旧代码序列化的消息仍然可以被新代码所解析。应该牢记新元素的默认值以便于新代码与旧代码序列化的消息进行交互。类似的,新代码序列化的消息同样可以被旧代码解析:旧代码解析时会简单的略过新字段。参考未知字段获取详细信息。
  • 字段可被移除,只要不再使用移除字段的字段编号即可。可能还会对字段进行重命名,或许是增加前缀 OBSOLETE_,或保留字段编号以保证后续不能重用该编号。

知识点:

field:message由一个个字段组成,一个字段的完整的二进制描述即<<编号,传输类型>,值>通常称为一个field,如下图。 在这里插入图片描述

  1. proto 是根据字段编号 (field_number) 进行序列化的而不是根据 key,即字段编号代表该字段在序列化时二进制字节流的顺序位置,所以在 grpc 的 service 端和 client 端的 proto 字段编码必须相同
  2. 在对一条消息(message)进行编码的时候是把该消息中所有的key-value对序列化成二进制字节流;key和value分别采用不同的编码方式
  3. 消息的二进制格式只使用消息字段的字段编号(field_num)作为Tag(key/键)的一部分,字段名和声名类型只能在解析端通过引用参考消息类型的定义(即.proto文件)才能确定。
  4. 解码的时候解码程序(解码器)读入二进制的字节流,解析出每一个key-value对;如果解码过程中遇到识别不出来的filed_num就直接跳过。这样的机制保证了即使该消息(message)添加了新的字段,也不会影响旧的编/解码程序正常工作。