05.Protocol Buffers技巧
翻译自: Techniques
本文讨论Protocol Buffers
在数据交换时,常用的一些设计模式。
序列化多个消息
如果要在一个文件或者一个流中写入多条消息,此时需要追踪消息的结尾位置与下一条消息的开始位置。Protocol Buffers
无法自定边界,也就是说,proto解析器无法确定消息的结尾位置。最简单的解决方案是在写入消息前,先写入固定长度的消息size值,在读取流时,先从流中读取固定长度的size,然后读取消息长度的数据,放到一个特定的buffer,再使用解析器解析这个buffer。(如果要拷贝部分字节到一个特定的buffer,可以看一下Java和C++类的CodedInputStream
类)
大型数据集合
Protocol Buffers
的设计不适用于大型数据处理,按照一般经验来说,超过1M字节的数据,就应该另选其它的方案了。
也就是说,Protocol Buffers
适合处理数据集中的独立元素。通常情况下,大型数据集实际上是小数据的集合,其中每个一元素都是结构化的数据。虽然Protocol Buffers
不适合处理整个数据集合,但是,可以使用Protocol Buffers
处理集合中的每一个元素。
Protocol Buffers
不包含任何处理大型数据集合的内置支持,因为实际应用中,不同的情况需要不同的处理方案,每个解决方案都需要开发一个独立库。
自描述消息
Protocol Buffers
不包含类型描述信息,所以,如果只给出一个原始消息,而没有相应的.proto
文件定义其类型,那么,解析消息将变的非常困难。
然而.proto
文件本身可以使用Protocol Buffers
来表示,源代码包中的src/google/protobuf/descriptor.proto
定义了所涉及消息类型格式。protoc
程序可以使用--descriptor_set_out
选项输出FileDescriptorSet
——代表一组.proto
文件。这样就可以定义自描述消息了。
syntax = "proto3";
import "google/protobuf/any.proto";
import "google/protobuf/descriptor.proto";
message SelfDescribingMessage {
// Set of FileDescriptorProtos which describe the type and its dependencies.
google.protobuf.FileDescriptorSet descriptor_set = 1;
// The message and its type, encoded as an Any message.
google.protobuf.Any message = 2;
}
通过使用像DynamicMessage这样的类(Java和C++可用),可以编写工具去操作SelfDescribingMessage
未在Protocol Buffers
库中包含这个功能的原因是在google内部从来没有使用过这个功能,所以在使用自描述消息之前,请检查您的平台是否支持此功能。