文章目录
1. protobuf 简介
命名:Protocol Buffers— 协议缓冲区
1.1. 发展背景
Protobuf 的诞生之初是为了解决服务端新旧协议(高低版本)兼容性问题,同时被寄予2 个特点:
- 可以很容易地引入新字段
- 数据格式可以用各种语言来处理(Java,C++ 等各种语言)
发展历程:
- 2001年在谷歌诞生
- 2008年2.0版本对外开源
- 2016年3.0版本发布
- 2022年更新至3.20
Protobuf 对外开源是从Protobuf2 开始
1.2. 优缺点
1.2.1. 优点
性能:
- 体积小,序列化后,数据大小可缩小3-10倍
- 序列化速度快,比XML和JSON快20-100倍
- 传输速度快,因为体积小,传输起来带宽和速度会有优化
使用:
- 使用简单,proto编译器自动进行序列化和反序列化
- 维护成本低,多平台仅需维护一套对象协议文件(.proto)
- 向后兼容性(扩展性)好,不必破坏旧数据格式就可以直接对数据结构进行更新
- 加密性好,Http传输内容抓包只能看到字节
使用范围:跨平台、跨语言(支持Java, Python, Objective-C, C+, Dart, Go, Ruby, and C#等),可扩展性好
1.2.2. 缺点
- 功能,不适合用于对基于文本的标记文档(如HTML)建模,因为文本不适合描述数据结构
- 通用性较差:json、xml已成为多种行业标准的编写工具,而Protobuf只是Google公司内部的工具
- 自解耦性差:以二进制数据流方式存储(不可读),需要通过.proto文件才能了解到数据结构
2. 使用
2.1. 消息类型
在 proto 中,所有结构化的数据都被称为 message。
syntax = "proto3";
package hello;
message helloworld
{
required int32 id = 1;
required string name = 2;
optional int32 age = 3;
}
如果开头第一行不声明 syntax = “proto3”;,则默认使用 proto2 进行解析。
声明package,来防止命名冲突。 Packages是可选的。
2.1.1. 字段限制
- required:消息体中必填字段,不设置会导致编解码异常;
- optional:消息体中可选字段;
- repeated:可重复字段(变长字段);
由于一些历史原因,repeated字段并没有想象中那么高效,新版本中允许使用特殊的选项来获得更高效的编码:
repeated int32 samples = 4 [packed=true];
2.1.2. 数据类型
完整数据类型映射—>《支持的全部数据类型》
.proto 类型 | C++类型 | Go 类型 | Java 类型 |
---|---|---|---|
double | double | float64 | double |
int32 | int32 | int32 | int |
int64 | int64 | int64 | long |
sint32 | int32 | int32 | int |
sint64 | int64 | int64 | long |
bool | bool | bool | boolean |
2.1.3. 分配字段编号
每个消息定义中的每个字段都有唯一的编号。
注意:
- 范围 1 到 15 中的字段编号需要一个字节进行编码;
- 范围 16 至 2047 中的字段编号需要两个字节;
- 最小字