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

and*_*opp 121 thrift asn.1 protocol-buffers avro

所有这些都提供了二进制序列化,RPC框架和IDL.我对它们与特性(性能,易用性,编程语言支持)之间的关键差异感兴趣.

如果您了解任何其他类似技术,请在答案中提及.

JUS*_*ION 95

ASN.1是ISO/ISE标准.它具有非常易读的源语言和各种后端,包括二进制和人类可读.作为一个国际标准(和那个旧的标准!)源语言有点厨房淡化(大致与大西洋有点湿),但是它非常明确,并且具有相当大的支持.(你也许可以找到任何语言的ASN.1库,如果你挖够硬你的名字,如果有可使用的,你可以在FFIs使用.良好的C语言库)是,是一种标准化的语言,痴迷记录和还提供了一些很好的教程.

节俭不是标准.它最初来自Facebook,后来是开源的,目前是一个顶级的Apache项目.它没有详细记录 - 尤其是教程水平 - 而且对我的(不可否认的简短)一瞥似乎没有添加任何其他的东西,以前的努力还没有(在某些情况下更好).为了公平起见,它开箱即用的语言数量相当可观,包括一些较为知名的非主流语言.IDL也模糊地像C一样.

协议缓冲区不是标准.它是一种Google产品,正在向更广泛的社区发布.它在开箱即用的语言方面有点受限(它只支持C++,Python和Java),但它确实有很多第三方支持其他语言(质量变化很大).谷歌几乎做许多事都使用Protocol Buffers他们的工作,所以它是一个战斗考验的,久经沙场的协议(虽然不是身经百战的ASN.1是,它具有更好的文件比不节俭,但是,作为一个谷歌产品,它很可能是不稳定的(在不断变化的意义上,不是不可靠的意义上).IDL也是类似C的.

所有上述系统都使用在某种IDL中定义的模式来生成目标语言的代码,然后在编码和解码中使用该目标语言.Avro没有.Avro的输入是动态的,它的模式数据在运行时直接用于编码和解码(在处理过程中有一些明显的成本,但对动态语言也有一些明显的好处,而且不需要标记类型等) .它的架构使用JSON,如果已经有一个JSON库,那么在新语言中支持Avro会更容易管理.同样,与大多数重新设计车轮的协议描述系统一样,Avro也没有标准化.

就个人而言,尽管我与它有着爱/恨的关系,但我可能会将ASN.1用于大多数RPC和消息传输目的,虽然它实际上没有RPC堆栈(你必须制作一个,但是IOC会这样做很简单).

  • 对于记录,Protocol Buffers总是按数字显式编码字段,如果有额外的字段,它在库级别绝不是错误,如果标记为可选或显式,则缺少的字段不是错误.因此,所有协议缓冲消息都具有"可扩展性". (7认同)
  • Avro更灵活,因为它允许在定义的模式上动态工作,或者生成样板类.根据我的经验,它非常强大:它的优势在于其丰富的功能,包括RPC生成器(这是Thrift的常见功能). (4认同)
  • 谢谢你的详细解释.但是版本控制怎么样,我听说protobuf可以处理它,其他库怎么样以及它们的共同用途呢?此外,似乎除了JSON之外,Avro现在还具有类似C语法的IDL. (3认同)
  • ASN.1支持通过`...`扩展标记进行手动版本控制,或通过模块头中的"可扩展性"自动进行自动版本控制.协议缓冲区IIRC支持手动版本控制.我不知道它是否支持隐含的可扩展性(并且懒得查找它).Thrift还支持一些版本控制,但同样它让我觉得它是一个没有隐含可扩展性的手动过程. (2认同)

Dee*_*101 37

我们刚刚对序列化器进行了内部研究,这里有一些结果(供我将来参考!)

Thrift =序列化+ RPC堆栈

最大的区别是Thrift不仅仅是一个序列化协议,它是一个完整的RPC堆栈,就像现代的SOAP堆栈.因此,在序列化之后,可以(但不强制要求)通过TCP/IP在机器之间发送对象.在SOAP中,您从一个WSDL文档开始,该文档完整地描述了可用的服务(远程方法)和期望的参数/对象.这些对象是通过XML发送的.在Thrift中,.thrift文件完整地描述了可用的方法,期望的参数对象和对象通过一个可用的序列化器(通过Compact Protocol有效的二进制协议,在生产中最流行)进行序列化.

ASN.1 =大爸爸

ASN.1是由80年代的电信人员设计的,由于有限的库支持而与CompSci人员出现的最新序列化器相比,使用起来很尴尬.有两种变体,DER(二进制)编码和PEM(ascii)编码.两者都很快,但DER更快,更有效.实际上,ASN.1 DER可以很容易地保持(有时甚至击败)30年后设计的序列化器,这证明了它的设计精良.它非常紧凑,比Protocol Buffers和Thrift小,只有Avro才能打败它.问题在于有很好的库支持,现在Bouncy Castle似乎是C#/ Java的最佳库.ASN.1在安全和加密系统方面处于领先地位并且不会消失,所以不要担心"未来的证据".得到一个好的图书馆......

MessagePack =包中间

它并不坏,但它既不是最快的,也不是最小的,也不是最好的支持.没有生产理由选择它.

共同

除此之外,它们非常相似.大多数是基本TLV: Type-Length-Value原理的变体.

协议缓冲区(Google发起),Avro(基于Apache,用于Hadoop),Thrift(Facebook发起,现在是Apache项目)和ASN.1(电信发起)都涉及一定程度的代码生成,您首先在序列化程序中表达数据- 特定格式,然后序列化程序"编译器"将通过code-gen阶段生成您的语言的源代码.然后,您的应用程序源将这些code-gen类用于IO.请注意,某些实现(例如:Microsoft的Avro库或Marc Gavel的ProtoBuf.NET)允许您直接装饰您的应用程序级POCO/POJO对象,然后库直接使用这些修饰的类而不是任何代码类的类.我们已经看到这个提供了提升性能,因为它消除了对象复制阶段(从应用程序级POCO/POJO字段到代码字段).

一些结果和一个现场项目一起玩

该项目(https://github.com/sidshetye/SerializersCompare)比较了C#世界中的重要序列化器.Java人们已经有类似的东西了.

1000 iterations per serializer, average times listed
Sorting result by size
Name                Bytes  Time (ms)
------------------------------------
Avro (cheating)       133     0.0142
Avro                  133     0.0568
Avro MSFT             141     0.0051
Thrift (cheating)     148     0.0069
Thrift                148     0.1470
ProtoBuf              155     0.0077
MessagePack           230     0.0296
ServiceStackJSV       258     0.0159
Json.NET BSON         286     0.0381
ServiceStackJson      290     0.0164
Json.NET              290     0.0333
XmlSerializer         571     0.1025
Binary Formatter      748     0.0344

Options: (T)est, (R)esults, s(O)rt order, (S)erializer output, (D)eserializer output (in JSON form), (E)xit

Serialized via ASN.1 DER encoding to 148 bytes in 0.0674ms (hacked experiment!)
Run Code Online (Sandbox Code Playgroud)

  • ASN.1还具有BER(基本编码规则),PER(压缩编码规则)和XER(XML编码规则).DER是BER的一种变体,主要用于加密,因为它保证了每个数据的唯一编码.BER和PER都比DER更有效.大多数库处理DER.有些不能正确处理所有BER结构.对于那些有兴趣了解更多信息的人:http://luca.ntop.org/Teaching/Appunti/asn1.html (3认同)
  • “有两种变体,DER(二进制)编码和 PEM(ascii)编码”。请记住,PEM 只是 BEGIN END 注释中的 Base-64 编码的二进制数据。该二进制数据可能是使用 DER 编码生成的,因此比较 PEM 和 DER 很奇怪。 (2认同)

Avn*_*ner 12

从性能角度来看,优步最近在其工程博客上评估了其中的几个库:

https://eng.uber.com/trip-data-squeeze/

他们的胜利者?MessagePack + zlib用于压缩

我们的目标是找到编码协议和压缩算法的组合,以最快的速度获得最紧凑的结果.我们测试了来自优步纽约市的2,219个伪随机匿名旅行的编码协议和压缩算法组合(作为JSON放入文本文件).

这里的教训是您的要求驱动哪个库适合您.对于优步而言,由于他们拥有的消息传递的无模式特性,他们无法使用基于IDL的协议.这消除了一堆选项.同样对他们而言,不仅是原始编码/解码时间发挥作用,而且还有静止数据的大小.

尺寸结果

尺寸结果

速度结果

在此输入图像描述


小智 11

ASN.1的一大优点是,它是专为规范 而非实现而设计的.因此,它非常擅长隐藏/忽略任何"真实"编程语言中的实现细节.

它的作用是ASN.1-Compiler将编码规则应用于asn1文件并从它们两者生成可执行代码.编码规则可以在EnCoding Notation(ECN)中给出,也可以是标准化的规则之一,如BER/DER,PER,XER/EXER.那就是ASN.1是类型和结构,编码规则定义了线编码,最后但并非最不重要的是编译器将它传递给您的编程语言.

据我所知,免费的编译器支持C,C++,C#,Java和Erlang.(很多昂贵的专利/许可证)商业编译器非常通用,通常是最新的,有时甚至支持更多的语言,但请看他们的网站(OSS Nokalva,Marben等).

使用这些技术指定完全不同的编程文化的各方(例如"嵌入式"人和"服务器农民")之间的接口是非常容易的:asn.1文件,编码规则,例如BER和例如UML交互图.不用担心它是如何实现的,让每个人都使用"他们的东西"!对我而言,它运作良好.顺便说一句:在OSS Nokalva的网站上,你可能会找到至少两本关于ASN.1的免费下载书籍(一个是Larmouth,另一个是Dubuisson).

恕我直言,大多数其他产品只尝试成为另一个RPC-stub-generator,为序列化问题注入了大量空气.好吧,如果有人需要,一个人可能没事.但对我来说,它们看起来像Sun-RPC的重新设计(从80年代末开始),但是,嘿,这也很好.


Sri*_*ana 6

微软的Bond(https://github.com/Microsoft/bond)在性能,功能和文档方面令人印象深刻.但是,截至目前,它并不支持许多目标平台(2015年3月13日).我只能假设它是因为它是非常新的.目前它支持python,c#和c ++.它被MS无处不在.我尝试过,对我来说,使用bond比使用prot更好,但是我也使用了thrift,我遇到的唯一问题是文档,我必须尝试很多东西来理解事情是如何完成的.

是邦德少的资源如下(https://news.ycombinator.com/item?id=8866694,https://news.ycombinator.com/item?id=8866848,https://microsoft.github.io/ bond/why_bond.html)


Sta*_*Man 5

对于性能,一个数据点是jvm-serializers基准测试 - 它是非常具体的小消息,但如果你在Java平台上可能会有所帮助.我认为一般来说,表现往往不是最重要的区别.另外:永远不要把作者的话当作福音; 许多广告声称是虚假的(例如,msgpack网站有一些可疑的声明;它可能很快,但信息非常粗略,用例不太现实).

一个很大的区别是是否必须使用模式(PB,至少是Thrift; Avro它可能是可选的; ASN.1我也认为; MsgPack,不一定).

另外:在我看来,能够使用分层的模块化设计是件好事; 也就是说,RPC层不应该规定数据格式,序列化.很遗

最后,在选择数据格式时,现在的性能并不排除使用文本格式.有快速的JSON解析器(和非常快的流式xml解析器); 当考虑脚本语言的互操作性和易用性时,二进制格式和协议可能不是最佳选择.