protobuf实践

01 Jun 2019

业务上统一用protobuf来定义数据交换. 实践中的一些记录.

生产中用prototool做检查构建流程.

JSON相关

对外, 尤其是web接口, 一般还是以JSON形式交互, 一些注意点.

JSON映射关系

从JSON转的一些选项:

需要注意一些外部交互的过程中, 有些不能很好的解析null等字段, 或者对于即便空字段也是有存在要求, 要么在前置沟通中明确下来, 否则就的做一些恶心的特殊处理.

数据类型

尽量使用枚举便于有效性校验, 但是统一将枚举按照integer处理, 保留枚举名的变更灵活性.

由于javascript不能原生支持 int64. int64 json 里面是string, 设计上尽量避免int64数据类型.

由于java/avro不支持unsigned, 设计上避免unsigned类型.

谨慎使用预定义的数据类型 (https://developers.google.com/protocol-buffers/docs/reference/google.protobuf) 现在我们仅允许用google.protobuf.Struct做一些map的需求, 如记录HTTP请求/响应头等信息.

枚举约束

通过枚举类型来约束可能的值, 以及方便各端避免magic number.

实践中不方便的点: proto3要求必须有0值枚举; 且枚举名要全局唯一, 不能够重复, 导致枚举命名非常罗嗦, 而且不能很方便的生成枚举到文本的双向映射. 局限了我们实际使用中的范畴.

Note that enum values use C++ scoping rules, meaning that enum values are siblings of their type, not children of it.

数据约束

proto3已经不支持required关键字. 实际生产中对于字段是否存在/合规还是挺重要的. 用字段注解工具生成对应的数据有效性约束逻辑.

数据演化

单值变列表(repeated)调整是向前兼容的, 这个是我们实践过程中非常有用的点. 因为保不齐某个字段就从单值变多值了.

不同于avro, 解析是按照tag来做, 很容易用做错误的消息解析还不报错. 使用中需要特别注意schema的管理, 以及配合消息约束校验来挡.

protoc插件扩展

protoc-gen-plugin机制非常完善. 结合一些业务需求, 我们做一些protoc插件开发, 如基于proto生成消息文档, 生成对应的数据库表定义, 生成avro定义等.

Reference

HOME