protocal buffers是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于(数据)通信协议、数据存储等。
protocal buffers是有一种灵活,高效,自动化机制的结构数据序列化方法-可类比xml,但是xml更小(3-10倍)、更快(20-100倍)、更为简单。
你可以定义数据的结构,然后使用特殊生成的源代码轻松的在各种数据流中使用各种语言进行编写和读取结构数据。你甚至可以更新数据结构,而不破坏由旧数据结构编译的已部署程序。
简单来讲, ProtoBuf 是结构数据序列化[1] 方法,可简单类比于 XML[2],其具有以下特点:
- 语言无关、平台无关。即protocol支持java、c++、python等多种语言,支持多平台
- 高效。相比较xml、json更快
- 扩展性、兼容性好。你可以更新数据结构,但是不会影响程序
序列化:将数据结构或对象转换成能够被存储和传输(例如网络传输)的格式,同时应当要保证这个序列化结果在之后(可能在另一个计算环境中)能够被重建回原来的结构数据或对象。
2.potocalbuf的语法 1. protocalbuf的存储文件格式为.proto// 例1: 在 xxx.proto 文件中定义 Example1 message
这里需要注意的是,如果想通过使用protocal编译器去编译这个文件,必须在文件的第一行定义语法的协议版本
syntax = "proto2";
message Example1 {
optional string stringVal = 1;
optional bytes bytesVal = 2;
message EmbeddedMessage {
optional int32 int32Val = 1;
optional string stringVal = 2;
}
optional EmbeddedMessage embeddedExample1 = 3;
repeated int32 repeatedInt32Val = 4;
repeated string repeatedStringVal = 5;
}
上面是一个完整的案例,下面对这个案例进行一个完整的解读:
1.message 关键字后跟上消息名称:
message xxx {
}
2.字段规则
message xxx {
// 字段规则:required -> 字段只能也必须出现 1 次
// 字段规则:optional -> 字段可出现 0 次或1次
// 字段规则:repeated -> 字段可出现任意多次(包括 0)
// 类型:int32、int64、sint32、sint64、string、32-bit ....
// 字段编号:0 ~ 536870911(除去 19000 到 19999 之间的数字)
字段规则 类型 名称 = 字段编号;
}
- 类型string,名为stringVal的optional可选字段,字段编号为1,此字段可出现0或1次
- 类型bytes,名为byteval的optional可选字段,字段编号为2,此字段可出现0或1次
- 类型EmbeddedMessage(自定义的内嵌message类型),名为embeddedExample1的optional可选字段,字段编号为3,此字段可出现0或1次
- 类型int32,名为repeatedInt32Val的repeated可重复字段,字段编号为4,此字段可出现任意多次(包括0)
- 类型string,名为repeatedStringVal的repeated可重复字段,字段编号为5,此字段可出现任意多次(包括0)
我们在 .proto 文件中定义了数据结构,这些数据结构是面向开发者和业务程序的,并不面向存储和传输。
当需要把这些数据进行存储或传输时,就需要将这些结构数据进行序列化、反序列化以及读写。那么如何实现呢?不用担心, ProtoBuf 将会为我们提供相应的接口代码。如何提供?答案就是通过 protoc 这个编译器
可通过如下命令生成相应的接口代码:
// $SRC_DIR: .proto 所在的源目录 // --cpp_out: 生成 c++ 代码 // $DST_DIR: 生成代码的目标目录 // xxx.proto: 要针对哪个 proto 文件生成接口代码 protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/xxx.proto
protoc -I=/usr/local/Cellar/protobuf/3.17.3/bin --java_out=/usr/local/Cellar/protobuf/3.17.3/bin message.proto
通过在protocal安装目录下的bin目录下执行这条语句(为什么要在bin目录下执行这条语句,类比一下windows下的环境变量就明白了),会在路径为/usr/local/Cellar/protobuf/3.17.3/bin下的路径下找message.protocal这个文件,通过protoc编译器去编译,在/usr/local/Cellar/protobuf/3.17.3/bin生成java文件(这里的–java_out可以改成python_out或者c++_out这两种方式,这也佐证了protocalbuf支持多种语言)
命令执行完之后的结构图:
对上面的案例进行进一步的修改,将生成的.java文件运行。
总结:protocalbuf相比较于json、xml这两种数据格式有传输效率高的优势。但是比较一种格式的好坏,我们需要从多个方面去看待,从个人理解来看,将数据格式分为两个维度来看,一个是数据结构化、一个数据序列化。这里的数据结构化主要面向开发或业务层面,数据序列化面向通信或存储层面,当然数据序列化也需要“结构”和“格式”,所以这两者之间的区别主要在于面向领域和场景不同,一般要求和侧重点也会有所不同。数据结构化侧重人类可读性甚至有时会强调语义表达能力,而数据序列化侧重效率和压缩。
- XML、JSON、ProtoBuf 都具有数据结构化和数据序列化的能力
- XML、JSON 更注重数据结构化,关注人类可读性和语义表达能力。ProtoBuf 更注重数据序列化,关注效率、空间、速度,人类可读性差,语义表达能力不足(为保证极致的效率,会舍弃一部分元信息)
- ProtoBuf 的应用场景更为明确,XML、JSON 的应用场景更为丰富。



