一、什么是protocol buffers

Protocol buffers是一个灵活的、高效的、自动化的用于对结构化数据进行序列化的协议,与XML相比,Protocol buffers序列化后的码流更小、速度更快、操作更简单。你只需要将要被序列化的数据结构定义一次(译注:使用.proto文件定义),便可以使用特别生成的源代码(译注:使用protobuf提供的生成工具)轻松的使用不同的数据流完成对这些结构数据的读写操作,即使你使用不同的语言(译注:protobuf的跨语言支持特性)。你甚至可以更新你的数据结构的定义(译注:就是更新.proto文件内容)而不会破坏依赖“老”格式编译出来的程序。

二、protocol buffers的工作流程

首先,你需要通过在.proto文件中定义protocol buffer的message类型来指定你想要序列化的数据结构,每一个protocol buffer message是一个逻辑上的信息记录,它包含一系列的键值对。这里展示一个最基本的.ptoto文件的例子,它定义了一个包含Person信息的message:

message Person {required string name = 1;required int32 id = 2;optional string email = 3;enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2;}message PhoneNumber {required string number = 1;optional PhoneType type = 2 [default = HOME];}repeated PhoneNumber phone = 4;
}

正如你所看见的那样,message的格式非常简单–每一个message类型都有一个或多个带有唯一编号的字段,每一个字段有一个字段名和一个字段类型,字段类型可以是数值类型(比如整形或浮点型)、booleans(布尔类型)、strings(字符串类型)、raw bytes、甚至(正如上面的例子)还可以是其他的protocol buffer message类型,这允许你可以分层次的组织你的数据结构。你可以单独指定每一个字段为optional fields(可选字段)、required fields(必须字段)、repeated fields(可重复字段)。下一篇博文将会对.proto文件进行更详细的描述。

一旦定义了你的message,你就可以根据你所使用的语言(译注:如JAVA、C++、Python等)使用protocol buffer提供的编译工具编译.proto文件生成数据访问类。这些类为每一个字段都提供了简单的访问器(比如name()和set_name()),同时还提供了将整个结构化数据序列化为原始字节数据以及从原始字节数据反序列化为结构化数据的方法(译注:C++中称之为函数)。例如,如果你使用的语言是C++,运行编译器编译上述的例子将生成一个名为Person的类,在你的应用程序中你可以使用这个类来填充、序列化和反序列化Person protocol buffer messages。之后你可能会写下如下类似的代码(译注:序列化):

Person person;
person.set_name("John Doe");
person.set_id(1234);
person.set_email("jdoe@example.com");
fstream output("myfile", ios::out | ios::binary);
person.SerializeToOstream(&output);

之后,你可以将你的message读回(译注:反序列化):

fstream input("myfile", ios::in | ios::binary);
Person person;
person.ParseFromIstream(&input);
cout << "Name: " << person.name() << endl;
cout << "E-mail: " << person.email() << endl;

你可以向你的message中添加新的字段而不会破坏前向兼容性;在解析时旧的二进制文件会简单的忽略掉新字段,所以,如果你的通信协议中使用protocol buffers作为数据交换格式,那么你可以扩展你的协议而不用担心会打乱现有的代码。

三、为什么不使用XML?

相对于XML,protocol buffers在序列化结构数据时拥有许多先进的特性:

1、更简单

2、序列化后字节占用空间比XML少3-10倍

3、序列化的时间效率比XML快20-100倍

4、具有更少的歧义性

5、自动生成数据访问类方便应用程序的使用

举个例子,如果你想描述一个具有name和email的person数据结构,在XML中,你需要这样做:

<person><name>John Doe</name><email>jdoe@example.com</email></person>

然而,在protocol buffers的message中(protocol buffers的文本格式)你需要这样做:

# Textual representation of a protocol buffer.
# This is *not* the binary format used on the wire.
person {name: "John Doe"email: "jdoe@example.com"
}

当这个message被编码成protocol buffer的二进制格式(上述的文本格式只是为了方便阅读、调试和编辑),它将可能占用28个字节长度并且仅需要100-200纳秒的解析时间。相比,XML版本的则至少需要占用69字节的空间(这是在移除XML中的空格、换行之后),同时,将耗费大约5000-10000纳秒的解析时间。

除此之外,手动操作protocol buffer更为方便,例如如下C++代码:

cout << "Name: " << person.name() << endl;
cout << "E-mail: " << person.email() << endl;

然而如果你使用XML,那么你将需要这样做:

cout << "Name: "<< person.getElementsByTagName("name")->item(0)->innerText()<< endl;
cout << "E-mail: "<< person.getElementsByTagName("email")->item(0)->innerText()<< endl;

事物总有两面性,和XML相比protocol buffers并不总是更好的选择,例如,protocol buffers并不适合用来描述一个基于文本的标记型文档(比如HTML),因为你无法轻易的交错文本的结构。另外,XML具有很好的可读性和可编辑性;而protocol buffers,至少在它们的原生形式上并不具备这个特点。XML同时也是可扩展、自描述的。而一个protocol buffer只有在具有message 定义(在.proto文件中定义)时才会有意义。

四、如何开始使用protocol buffers?

首先,可以在这里下载安装包或者源码包

https://developers.google.com/protocol-buffers/docs/downloads#release-packages

这包含了针对JAVA、Python和C++编译器的完整源码,同时包含了你所需要的I/O和测试类。为了完成编译和安装,请参照README文件。

一旦你完成了编译和安装,那么就可以开始使用protocol buffers了,后续的博文将会对C++和JAVA语言的具体使用细节进行阐述。

五、proto3介绍

我们最新的版本version 3 alpha release引进了一个新的语言版本–Protocol Buffers version 3 (称之为proto3),它在我们现存的语言版本(proto2)上引进了一些新特性。proto3简化了protocol buffer language,这使其可以更便于使用和支持更多的编程语言:我们现在的alpha release版本可以让你能产生JAVA、C++、Pthyon、JavaNano、Ruby、Objective-C和C#版本的protocol buffer code,不过可能有时会有一些局限性。另外,你可以使用最新的Go protoc插件来产生Go语言版本的proto3 code,这可以从golang/protobuf Github repository获取。

我们现在只推荐你使用proto3:

1、如果你想尝试在我们新支持的语言中使用protocol buffers

2、如果你想尝试我们最新开源的RPC实现gRPC(目前仍处于alpha release版本),我们建议你为所有的gRPC 服务器和客户端都使用proto3以避免兼容性问题。

注意两个版本的语言APIs并不是完全兼容的,为了避免给原来的用户造成不便,我们将会继续维护之前的那个版本(译注:proto2)。

六、最后说一点历史

Protocol buffers最初被Google开发用来作为处理索引服务器的request/response协议。在protocol buffers诞生之前,有一个需要手动编码/解码requests、responses的协议,这个协议支持一个数字版本号,这导致了一个非常丑陋的代码,如下所示:

if (version == 3) {...} else if (version > 4) {if (version == 5) {...}...}

很显然的,格式化的协议也导致了复杂的新版本推出问题,因为开发人员必须确保所有服务器请求的发起者和实际的请求处理者之间都要理解新的协议。

Protocol buffers就是用来解决这些问题的:

1、可以很容易的插入新字段,中间的服务器可以简单的解析它而不需要了解所有字段。

2、格式更具有自描述性,可以被不同的语言处理(比如JAVA、C++、Python等)。

3、自动产生序列化和反序列化代码从而避免了手动解析。

4、除了应用在具有短暂生命周期的RPC请求中,人们开始使用protocol buffers 作为一种便利的自描述格式来存储数据(比如在Bigtable中)。

5、服务器的RPC接口开始被声明为协议文件的一部分,通过protocol 编译器产生stub类,该类可以被用户根据实际实现的服务器接口进行重写。

protocol buffers使用说明相关推荐

  1. Protocol Buffers简明教程

    随着微服务架构的流行,RPC框架渐渐地成为服务框架的一个重要部分.在很多RPC的设计中,都采用了高性能的编解码技术,Protocol Buffers就属于其中的佼佼者.Protocol Buffers ...

  2. Google Protocol Buffers介绍

    Google Protocol Buffers(简称Protobuf),是Google的一个开源项目,它是一种结构化数据存储格式,是Google公司内部的混合语言数据标准,是一个用来序列化(将对象的状 ...

  3. 架构师之路 — 分布式系统 — Protocol Buffers 序列化协议

    目录 文章目录 目录 Protocol Buffers 序列化协议 定义数据结构 序列化传输 Protocol Buffers 序列化协议 Protocol Buffers 是一种高性能的.语言无关的 ...

  4. 在Quick-cocos2dx中使用云风pbc解析Protocol Buffers,支持win、mac、ios、android

    本例主要介绍 如何将 pbc 集成到quick-cocos2dx框架中,让我们的cocos2dx客户端Lua拥有编解码Protocol Buffers能力. 参考: 云风pbc的用法: http:// ...

  5. 序列化--反序列化:Schema evolution in Avro, Protocol Buffers and Thrift

    当想要数据, 比如对象或其他类型的, 存到文件或是通过网络传输, 需要面对的问题是序列化问题 对于序列化, 当然各个语言都提供相应的包, 比如, Java serialization, Ruby's ...

  6. Go 支持Protocol Buffers的配置

    Go 支持Protocol Buffers的配置 安装 protoc (The protocol compiler)是由C++写的,支持的 C++.Java.Python.Objective-C.C# ...

  7. Protocol Buffers java

    Protocol Buffers https://developers.google.cn/protocol-buffers/ 一. 例 addressbook.proto.syntax = &quo ...

  8. Protocol Buffers 在 iOS 中的使用

    翻译自:Introduction to Protocol Buffers on iOS 对大多数的应用来说,后台服务.传输和存储数据都是个重要的模块.开发者在给一个 web service 写接口时, ...

  9. MessagePack, Protocol Buffers和Thrift序列化框架原理和比较说明

    第1部分messagepack说明 1.1messagepack的消息编码说明 为什么messagepack比json序列化使用的字节流更少, 可通过图1-1.图1-2有个直观的感觉. 图1-1mes ...

最新文章

  1. Android Textview 实现版权符号© 的 实现
  2. springcloud是什么_阿里P8道出,入职阿里必会199道SpringCloud面试题,你能掌握多少?...
  3. VC四种程序启动画面的制作方法
  4. 手把手教你EMD算法原理与Python实现(更新)
  5. python编程语言好学吗-转行零基础该如何学习python?很庆幸,三年前的我选对了...
  6. C++ 在继承中虚函数、纯虚函数、普通函数,三者的区别
  7. linux to extract contents between patterns
  8. 惠普 g5 服务器 centos安装系统,hp 380G5 安装centos 7
  9. android studio 工程demo例子,Android Studio 实现跑马灯微项目实例
  10. 【HTML】前端性能优化之CDN和WPO的比较
  11. 一个周内上线50个增长策略,竟然能这么高效!
  12. 汇报时,如何让老板快速抓住重点?—— 黄金三步法
  13. 百度云服务器安装git并做远程仓库
  14. POI API 创建Excel 文档
  15. 华硕2020年显卡_送自己最好的新年游戏礼物,2020年新春显卡市场完全解析
  16. [20190524]DISABLE TABLE LOCK(12c).txt
  17. 从全球制造业的迁移史,看中国制造业未来会怎么走?
  18. 日常随笔——m1 macbook安装和配置qt
  19. Hadoop-kms总结
  20. OsgEarth星空背景

热门文章

  1. 打印心形c语言,C语言打印心形
  2. java的方法调用中分不清_java中不太清晰的知识点
  3. 128位java_Java:如何使用CFB和无填充实现128位AES
  4. mysql in优化_MySQL的一次优化记录 (IN子查询和索引优化)
  5. java excil表格开发_JAVA导出Excel电子表格的方法
  6. jquery点击弹出播放视频并显示遮罩层
  7. Oracle中通过substr和instr实现截取指定字符之间的字符串:
  8. GitHub删除已有文件和提交文件的方法
  9. leetcode628. 三个数的最大乘积(简单,我觉得你不会)
  10. leetcode412. Fizz Buzz