thrift和google protobuffer各有啥优劣

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了thrift和google protobuffer各有啥优劣相关的知识,希望对你有一定的参考价值。

Google就是Google,就算是推白菜出来,也一样能让人侧目。其实protocol buffers也不是什么新鲜的概念,且不说传统的ASN.1, ICE这些有点类似的东西,facebook一年前就推出了thrift,应该说定位是非常的接近的。也有谣传说是先有了protocol buffers在google内部流行,然后google的人跳槽到facebook,就出了thrift这个东西……呵呵,停止八卦,言归正传。 观察法看到的优缺点 Thrift: 支持的语言更广泛一些c++, java, python,ruby, csharp, haskell, ocmal, erlang, cocoa, php, squeak(真够变态的) protobuf 目前还是只支持c++, java, python, 其他语言有待开发. Thrift提供的功能更丰富一些: Thrift提供了简单的RPC构架(其实不简单了, block, nonblock的都有了…..) protobuf好像一心一意做好自己的事情,只提供了序列化和反序列化的功能。 Thrift支持多种协议格式. Thrift的代码实现,有专门的TProtocol和TTransport抽象,相互配合,可以实现多种协议,方便集成各种传输方式。至少目前Thrift就能使用json作为序列化协议。 protobuf好像只安心一种协议,并下决心把这个格式做好。输入输出也是标准的stream. 认真的说也不完全这样,protobuf为了调试方便,也提供了Text_Fromat功能,这个也算一个nonbinary格式支持,这样看来完全新协议还是有可能的。 Thrift还提供了不少语言的C module(性能啊,都是性能啊) protobuf全部pure language实现, 反正现在已经都5到10倍速度了,不在乎了….. thrift目前不支持Windows平台,至少c++语言的runtime library和generated code是不不能在windows平台上使用的。(这真有点让人难以接受啊,现代科技这么发达,还有怪兽boost,支持windows有这么难吗?) protobuf没有这个问题,提供了visual studio的项目文件,可以很顺利的在windows平台下编译。(题外话: 如果不知道googletest怎么在windows平台上使用,可以参考protobuf的测试用例)。 The Thrift C++ runtime library does not currently work on Windows. This means that you’ll be able to compile ThriftIDL files to C++/Java/Python/etc., but you won’t be able to compile and run the generated C++ code under Windows. thrift wiki protobuf侧重点是语言表达,同时在存储效率上也下了不少功夫。用protobuf来直接读写数据结构相当的方便。 thrift侧重点是构建夸语言的可伸缩的服务,特点就是支持的语言多,同时提供了完整的rpc service framework,可以很方便的直接构建服务,不需要做太多其他的工作。 数据类型相对固定的情况下,不论是thrift还是protobuf都会比直接处理xml要方便很多。不管是dom还是类sax,总没有直接出数据结构访问来的方便啊。 提问者 的感言: 谢谢你帮了我大忙! 参考技术A 数据类型

protobuf

thrift

protobuf

thrift

protobuf

thrift

protobuf

thrift

double

double

float

byte

i16

int32

i32

int64

i64

uint32

uint64

sint32

sint64

fixed32

fixed64

sfixed32

sfixed64

bool

bool

string

string

bytes

binary

message

struct

enum

enum

service

service

综合对比

protobuf

thrift

功能特性

主要是一种序列化机制

提供了全套RPC解决方案,包括序列化机制、传输层、并发处理框架等

支持语言

C++/Java/Python

C++, Java, Python, Ruby, Perl, PHP, C#, Erlang, Haskell

易用性

语法类似,使用方式等类似

生成代码的质量

可读性都还过得去,执行效率另测

升级时版本兼容性

均支持向后兼容和向前兼容

学习成本

功能单一,容易学习

功能丰富、学习成本高

文档&社区

官方文档较为丰富,google搜索protocol buffer有2000W+结果,google group被墙不能访问

官方文档较少,没有API文档,google搜索apache thrift仅40W结果,邮件列表不怎么活跃

性能对比
由于thrift功能较protobuf丰富,因此单从序列化机制上进行性能比较,按照序列化后字节数、序列化时间、反序列化时间三个指标进行,对thrift的二进制、压缩、protobuf三种格式进行对比。

测试方法:取了15000+条样本数据,分别写了三个指标的测试程序,在我自己的电脑上执行,其中时间测试循环1000次,总的序列化/反序列化次数1500W+。

平均字节数:

thrift二进制

535

thrift压缩

473

protobuf

477

序列化(1500W次)时间(ms):

thrift二进制

306034

thrift压缩

304256

protobuf

177652

反序列化(1500W次)时间(ms):

thrift二进制

287972

thrift压缩

315991

protobuf

157192

thrift的时间测试可能不是很准,由于thrift产生代码的复杂性,编写的测试代码为了适应其接口,在调用堆栈上可能有一些额外开销。
参考技术B thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, javascript, Node.js, Smalltalk, and OCaml 这些编程语言间无缝结合的、高效的服务。

Protobuffer教程

目录

  1. 什么是protobuffer?
  2. protobuffer是如何工作的?
  3. 为什么不用xml?

1.什么是protobuffer?

protobuffer是一种灵活,高效,自动化的机制,用于序列化结构化数据 - 想想XML,但更小,更快,更简单。您可以定义数据的结构化时间,然后可以使用特殊生成的源代码轻松地在各种数据流中使用各种语言编写和读取结构化数据。您甚至可以更新数据结构,而不会破坏根据“旧”格式编译的已部署程序。

 

2.protobuffer是如何工作的?

您可以通过在.proto文件中定义协议缓冲区消息类型来指定您希望如何构建序列化信息每个协议缓冲区消息都是一个小的逻辑信息记录,包含一系列名称 - 值对。以下.proto是定义包含有关人员信息的消息文件的一个非常基本的示例

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;
}

如您所见,消息格式很简单 - 每种消息类型都有一个或多个唯一编号的字段,每个字段都有一个名称和一个值类型,其中值类型可以是数字(整数或浮点数),布尔值,字符串,字节,甚至(如上例所示)其他协议缓冲区消息类型,允许您分层次地构建数据。您可以指定可选字段,必填字段和重复字段。您可以.protoProtocol Buffer Language Guide中找到有关编写文件的更多信息

一旦定义了消息,就可以在.proto文件上运行应用程序语言的协议缓冲区编译器来生成数据访问类。这些为每个字段(如name()set_name()提供了简单的访问器,以及将整个结构序列化/解析为原始字节的方法 - 例如,如果您选择的语言是C ++,则在上面的示例中运行编译器将生成了Person类然后,您可以在应用程序中使用此类来填充,序列化和检索Person协议缓冲区消息。然后你可以写一些这样的代码:

 

Person person;
person.set_name("John Doe");
person.set_id(1234);
person.set_email("[email protected]");
fstream output("myfile", ios::out | ios::binary);
person.SerializeToOstream(&output);

然后可以这样读入消息

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

您可以在消息格式中添加新字段,而不会破坏向后兼容性; 旧的二进制文件在解析时只是忽略新字段。因此,如果您的通信协议使用协议缓冲区作为其数据格式,则可以扩展协议,而无需担心破坏现有代码。

您将在API参考部分找到有关使用生成的协议缓冲区代码的完整参考,您可以在协议缓冲区编码中找到有关如何编码协议缓冲区消息的更多信息

 

3.为什么不使用XML?

对于序列化结构化数据,protobuffer比XML具有许多优点。protobuffer:

  • 更简单
  • 比小3到10倍
  • 快20到100倍
  • 不那么暧昧
  • 生成更易于以编程方式使用的数据访问类

例如,假设你想要定义一个拥有一个name和email的person在XML中,您需要:

1 <person>
2     <name>John Doe</name>
3     <email>[email protected]</email>
4   </person>

而使用相应的protobuffer是:

1 # Textual representation of a protocol buffer.
2 # This is *not* the binary format used on the wire.
3 person {
4   name: "John Doe"
5   email: "[email protected]"
6 }

当此消息被编码为protobuffer二进制格式(上面的文本格式只是用于调试和编辑的方便的人类可读表示)时,它可能长达28个字节并且需要大约100-200纳秒来解析。如果删除空格,XML版本至少为69个字节,并且需要大约5,000-10,000纳秒才能解析。

此外操作protobuffer数据更容易:

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

如果你是用xml,可能是这个样子:

1  cout << "Name: "
2        << person.getElementsByTagName("name")->item(0)->innerText()
3        << endl;
4   cout << "E-mail: "
5        << person.getElementsByTagName("email")->item(0)->innerText()
6        << endl;

但是,protobuffer并不总是比XML更好的解决方案 - 例如,protobuffer不是使用标记(例如HTML)对基于文本的文档建模的好方法,因为您无法轻松地将结构与文本交错。此外,XML是人类可读的和人类可编辑的; XML在某种程度上也是自我描述的。只有拥有消息定义(.proto文件)时,protobuffer才有意义

 

以上是关于thrift和google protobuffer各有啥优劣的主要内容,如果未能解决你的问题,请参考以下文章

protobuffer java中文乱码怎么解决

Windows 上的 Thrift / Google 协议缓冲区

gRPC的接口描述语言ProtoBuffer

Apache Thrift、Google Protocol Buffers、MessagePack、ASN.1 和 Apache Avro 之间的主要区别是啥?

zeroc ICE和thrift哪个好使

C ++ libcurl缓存数据响应