协议缓冲区是什么?有什么强力竞争者?
【引言】
在这篇文章《gRPC技术优势在哪里?有什么缺点和应对策略?》下面,有朋友对于“协议缓冲区”存在一些疑问, 我们现在就来学习和探究一下协议缓冲区。
【概念】
协议缓冲区(Protobuf)是一种将结构化数据序列化的方法。
它在程序开发中应用广泛,可以用于相互通信或数据存储。
它包括两部分,一部分是描述某些数据结构的接口描述语言, 另一部分是从该描述语言中生成源代码的程序,这个程序用于生成或解析这些结构化数据的字节流。
【设计目标】
最初Google开发了协议缓冲区供内部使用,并在开放源码许可下提供了多种语言的代码生成器。
协议缓冲区的设计目标强调了简单性和性能。特别地,它的设计目标是比XML更小、更快。
【发展状况】
协议缓冲区(Protocol Buffers)在Google公司被广泛用于存储和交换各种结构化信息。该方法作为定制的远程过程调用(RPC)系统的基础,在Google公司几乎所有的机器间通信中都使用了该方法。
协议缓冲区类似于Apache Thrift(Facebook使用的)或微软Bond协议,Google也提供了一个具体的RPC协议栈,用于服务的定义和开发,称为gRPC。
【工作方式】
数据结构(也称为消息)和服务的设计存放在一个proto定义文件(.proto)中,然后用类似protoc的工具进行编译。这种编译生成的代码可以被这些数据结构的发送者或接收者调用。
例如,example.pb.cc和example.pb.h就是从example.proto生成的。它们为 example.proto 中的每个消息和服务定义了 C++ 类。
老实说,消息被序列化为二进制数据格式以后,是紧凑的、前向和后向兼容的,但是它不是自描述的。也就是说,如果没有外部规范,就没有办法知道字段的名称、含义或完整的数据类型。
官方支持的实现虽然包括一个ASCII序列化格式,这种格式是自描述的,但是却失去了前向和后向兼容的行为,因此对于除调试以外的应用来说并不是一个好的选择。
协议缓冲区的主要目的是为了方便网络通信,它的简单性和高速度使得协议缓冲区可以逐步替代以数据为中心的C++类和结构,尤其是在需要与其他语言或系统互操作的情况下,这个替代尤为必要。
【例子】
协议缓冲区的特定使用模式将数据类型与字段名关联起来,使用整数来标识每个字段。
//polyline.proto
syntax = "proto2";
message Point {
required int32 x = 1;
required int32 y = 2;
optional string label = 3;
}
message Line {
required Point start = 1;
required Point end = 2;
optional string label = 3;
}
message Polyline {
repeated Point point = 1;
optional string label = 2;
}
"Point"消息定义了两个必选数据项,即x和y,标签项是可选的。每个数据项都有一个标识号。标识号定义在等号之后。例如,x的标识号为1。
"Line"和 "Polyline"消息都使用了Point,分别定义了在协议缓冲区中的组成结构。Polyline有一个重复字段,就像一个向量(Vector)。
这个设计结构可以被编译成一种或多种编程语言的代码。使用类似Google protoc 的编译工具,可以生成C++、Java 或 Python等20多种编程语言的代码。
例如,下面是使用上述定义的数据结构的例子-polyline.cpp:
// polyline.cpp
#include "polyline.pb.h" // generated by calling "protoc polyline.proto"
Line* createNewLine(const std::string& name) {
// create a line from (10, 20) to (30, 40)
Line* line = new Line;
line->mutable_start()->set_x(10);
line->mutable_start()->set_y(20);
line->mutable_end()->set_x(30);
line->mutable_end()->set_y(40);
line->set_label(name);
return line;
}
Polyline* createNewPolyline() {
// create a polyline with points at (10,10) and (20,20)
Polyline* polyline = new Polyline;
Point* point1 = polyline->add_point();
point1->set_x(10);
point1->set_y(10);
Point* point2 = polyline->add_point();
point2->set_x(20);
point2->set_y(20);
return polyline;
}
【编译工具现状】
proto2提供了用于生成C++、Java、C#和Python的编译生成器 。
proto3提供了生成C++、Java(包括JavaNano,一种用于低资源环境的语言变种)、Python、Go、Ruby、Objective-C和C#的编译生成器。
第三方的工具可以生成Javascript, C、Dart、Haskell、Perl、PHP、R、Rust、Scala、Swift和Julia的代码。
【关联工具-FlatBuffers】
FlatBuffers是一个免费的软件库,它采用了类似于Protocol Buffers、Thrift、Apache Avro、SBE和Cap'n Proto的序列化格式,主要由Wouter van Oortmerssen编写,并由Google开源。
它支持 "零拷贝"解串,这样访问序列化的数据就不需要先将其复制到内存的一个单独部分,这使得数据访问过程快很多,这个速度是相较于数据格式需要更广泛处理的机制而言的,比如JSON、CSV,以及在许多情况下的协议缓冲区处理。
然而与其他序列化格式相比, FlatBuffers的处理通常需要更多的代码,而且有些操作是无法实现的(比如一些突变操作)。
FlatBuffers是GitHub上的一个热门项目,截至2020-05-13,GitHub上有14.3K个星星,395个贡献者,2.2k个分叉,649个观看者。
FlatBuffers可以生成C++、C#、C、C、Go、Java、JavaScript、PHP、Python和Rust代码。该编译器可以在Android、Microsoft Windows、Mac OS X和Linux上运行。 同时,使用FlatBuffers进行序列化的游戏和其他程序也可以在许多其他操作系统上运行,包括iOS、Amazon的Fire OS和Windows Phone上。
Oortmerssen最初开发FlatBuffers是为了用于在游戏开发和类似的应用中使用序列化数据访问。
尽管FlatBuffers有自己的接口定义语言来定义结构化的数据,它也支持用协议缓冲区的.proto格式。
【小结】
本文对协议缓冲区从概念,设计目标,工作方式和例子等方面进行了学习和探讨,希望对各位朋友有用。
欢迎讨论。
- 点赞
- 收藏
- 关注作者
评论(0)