协议缓冲区是什么?有什么强力竞争者?

举报
Jet Ding 发表于 2020/09/30 15:23:39 2020/09/30
【摘要】 协议缓冲区(Protobuf)是一种将结构化数据序列化的方法。它在程序开发中应用广泛,可以用于相互通信或数据存储。它包括两部分,一部分是描述某些数据结构的接口描述语言, 另一部分是从该描述语言中生成源代码的程序,这个程序用于生成或解析这些结构化数据的字节流。

【概念】

协议缓冲区(Protobuf)是一种将结构化数据序列化的方法。

 

它在程序开发中应用广泛,可以用于相互通信或数据存储。

 

它包括两部分,一部分是描述某些数据结构的接口描述语言, 另一部分是从该描述语言中生成源代码的程序,这个程序用于生成或解析这些结构化数据的字节流。

 

【设计目标】

最初Google开发了协议缓冲区供内部使用,并在开放源码许可下提供了多种语言的代码生成器。

 

协议缓冲区的设计目标强调了简单性和性能。特别地,它的设计目标是比XML更小、更快。

 

【发展状况】

 

协议缓冲区(Protocol Buffers)在Google公司被广泛用于存储和交换各种结构化信息。该方法作为定制的远程过程调用(RPC)系统的基础,在Google公司几乎所有的机器间通信中都使用了该方法。

 

协议缓冲区类似于Apache ThriftFacebook使用的)或微软Bond协议,Google也提供了一个具体的RPC协议栈,用于服务的定义和开发,称为gRPC

 

【工作方式】

 

数据结构(也称为消息)和服务的设计存放在一个proto定义文件(.proto)中,然后用类似protoc的工具进行编译。这种编译生成的代码可以被这些数据结构的发送者或接收者调用。

例如,example.pb.ccexample.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"消息定义了两个必选数据项,即xy,标签项是可选的。每个数据项都有一个标识号。标识号定义在等号之后。例如,x的标识号为1

 

"Line" "Polyline"消息都使用了Point,分别定义了在协议缓冲区中的组成结构。Polyline有一个重复字段,就像一个向量(Vector)

 

这个设计结构可以被编译成一种或多种编程语言的代码。使用类似Google protoc 的编译工具,可以生成C++Java  Python20多种编程语言的代码。

 

例如,下面是使用上述定义的数据结构的例子-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++JavaC#Python的编译生成器 

 

proto3提供了生成C++Java(包括JavaNano,一种用于低资源环境的语言变种)、PythonGoRubyObjective-CC#的编译生成器。

 

第三方的工具可以生成Javascript, CDartHaskellPerlPHPRRustScalaSwiftJulia的代码。

 

【关联工具-FlatBuffers

 

FlatBuffers是一个免费的软件库,它采用了类似于Protocol BuffersThriftApache AvroSBECap'n Proto的序列化格式,主要由Wouter van Oortmerssen编写,并由Google开源。

 

它支持 "零拷贝"解串,这样访问序列化的数据就不需要先将其复制到内存的一个单独部分,这使得数据访问过程快很多,这个速度是相较于数据格式需要更广泛处理的机制而言的,比如JSONCSV,以及在许多情况下的协议缓冲区处理。

 

然而与其他序列化格式相比, FlatBuffers的处理通常需要更多的代码,而且有些操作是无法实现的(比如一些突变操作)。

 

FlatBuffersGitHub上的一个热门项目,截至2020-05-13GitHub上有14.3K个星星,395个贡献者,2.2k个分叉,649个观看者。

 

FlatBuffers可以生成C++C#CCGoJavaJavaScriptPHPPythonRust代码。该编译器可以在AndroidMicrosoft WindowsMac OS XLinux上运行。 同时,使用FlatBuffers进行序列化的游戏和其他程序也可以在许多其他操作系统上运行,包括iOSAmazonFire OSWindows Phone上。

 

Oortmerssen最初开发FlatBuffers是为了用于在游戏开发和类似的应用中使用序列化数据访问。

 

尽管FlatBuffers有自己的接口定义语言来定义结构化的数据,它也支持用协议缓冲区的.proto格式

 

小结

本文对协议缓冲区从概念,设计目标,工作方式和例子等方面进行了学习和探讨,希望对各位朋友有用。


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。