protobuf 是一个灵活的、高效的、自动化的用于对结构化数据进行序列化的协议,与 XML 相比,protobuf 序列化后的码流更小、速度更快、操作更简单。序列化后字节占用空间比 XML 少3-10倍,序列化的时间效率比 XML 快20-100倍。你只需要将要被序列化的数据结构定义一次(使用 .proto 文件定义),便可以使用特别生成的源代码(使用 protobuf 提供的生成工具)轻松的使用不同的数据流完成对这些结构数据的读写操作,即使你使用不同的语言(protobuf 的跨语言支持特性)。你甚至可以更新你的数据结构的定义(更新 .proto 文件内容)而不会破坏依赖之前编译出来的程序。
1. 优点
protobuf 优点:
- 性能好,效率高;
- 代码生成机制,数据解析类自动生成;
- 支持前后兼容;
- 支持多语言(c++, java, go, python)
2. 数据结构
protobuf 使用 .proto 文件定义数据结构。
syntax = "proto3";
package protobuf;
option java_package = "com.aaron.protobuf";
message msg {
required int32 = 1;
optional string = 2;
repeated bytes = 3;
message address {
string city = 1;
}
repeated address = 4;
}
2.1 域修饰符
域修饰符用于表示域出现情况。
- required,表示该域一定出现,必须要设值,一般不推荐使用;
- optional,表示该域是可选的,可能存在也可能不存在;
- repeated,表示该域是一个数组。
2.2 域类型
域类型用于修饰域的类型,域类型有 bool, bytes, int32, int64, uint32, uint64, float, double, string等。
2.3 域名
域名只是作为域的一个参考,使域更有可读性,protobuf 确定域是根据字段编号。
2.4 字段编号
protobuf 是根据字段编号来确定域的,域名只是一个参考,字段编号不可重复,可以不连续,[19000 ~ 19999] 被 protobuf 保留。
3. 兼容
protobuf 有很好的兼容性,前后都兼容。
- 向前兼容。版本升级后,新版 protobuf 在解析旧版二进制文件时,会给不存在属性添加默认值,如 int 默认是0,字符串默认是空字符串;
- 向后兼容。版本升级后,旧版 protobuf 在解析新版二进制文件时,会忽略掉新的字段;
- 类型兼容。修改字段类型时,protobuf 在解二进制文件时,发型类型不匹配,会使用默认值代替。
4. 使用
以 java 为例,展示如何使用 protobuf。从 .proto 的定义中生成代码,我们通过 protobuf 的编译器来完成。
4.1 添加 protobuf-java 依赖
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.0.0</version>
</dependency>
4.2 添加 protobuf 编译插件
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.0</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.0.0-beta-2:exe:${os.detected.classifier}
</protocArtifact>
<protoSourceRoot>src/main/proto</protoSourceRoot>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
4.3 生成代码
Maven -> Plugins 运行 prtobuf:compile 即可生成代码