Apachethift、谷歌协议缓冲、 MessagePack、 ASn.1和 ApacheAvro 之间的主要区别是什么?

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

如果你知道任何其他类似的技术,请在回答中提到它。

39638 次浏览

ASN.1 是 ISO/ISE 标准。它有一个非常可读的源语言和各种后端,二进制和人类可读。成为一个国际标准(而且是一个老标准!)源语言有点像厨房用语(就像大西洋有点潮湿一样) ,但是它非常具体,并且有相当多的支持。(如果你足够努力的话,你可以找到任何你命名的语言的 ASN.1库,如果没有好的 C 语言库,你可以在 FFI 中使用。)作为一种标准化语言,它有大量的文档,并且还有一些很好的教程可用。

节俭不是标准。它最初来自 Facebook,后来开源,目前是一个顶级的 Apache 项目。它没有很好的文档记录——特别是教程级别——而且在我看来(不可否认的是很简短) ,它似乎没有添加任何其他以前的努力没有做到的东西(在某些情况下更好)。公平地说,它支持的开箱即用的语言数量令人印象深刻,其中包括一些知名度较高的非主流语言。IDL 也有点像 C。

协议缓冲不是一个标准。这是一个正在向更广泛的社区发布的谷歌产品。它在开箱即用的语言支持方面有点局限(它只支持 C + + 、 Python 和 Java) ,但它确实对其他语言(质量高度可变)有很多第三方支持。谷歌几乎所有的工作都使用协议缓冲,所以它是一个经过战斗考验的、经过战斗磨练的协议(尽管不像 ASN 1那样经过战斗磨练)。它的文档比 Thrift 好得多,但是,作为一个 Google 产品,它极有可能是不稳定的(在不断变化的意义上,而不是在不可靠的意义上)。IDL 也是类 C 的。

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

就我个人而言,尽管我对 ASN.1又爱又恨,但我可能会使用 ASN.1来实现大多数 RPC 和消息传输的目的,尽管它并没有真正的 RPC 堆栈(你必须制作一个,但 IOC 使它足够简单)。

对于性能,一个数据点是 Jvm- 序列化程序基准测试——它是非常特定的小消息,但是如果您在 Java 平台上,它可能会有所帮助。我认为,总的来说,表现往往不是最重要的差异。还有: 绝不要把作者的话当作福音; 许多广告声明都是假的(例如 msgpack 网站就有一些可疑的声明; 它可能很快,但信息非常粗略,用例不太现实)。

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

另外: 在我看来,能够使用分层的、模块化的设计是好的; 也就是说,RPC 层不应该规定数据格式、序列化。不幸的是,大多数候选人都会将这些信息紧密捆绑在一起。

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

关于 ASN.1的一件大事是,它是为 规格 没有实现而设计的。因此,它非常善于在任何“真正的”编程语言中隐藏/忽略实现细节。

ASN 1-Compiler 的工作是将编码规则应用到 asn1-文件,并从这两个文件中生成可执行代码。编码规则可以在编码符号(ECN)中给出,也可以是标准规则之一,如 BER/DER、 PER、 XER/EXER。 即 ASN.1是类型和结构,编码规则定义有线编码,最后但并非最不重要的编译器将其传输到您的编程语言。

据我所知,免费编译器支持 c、 c + + 、 c # 、 Java 和 Erlang。商业编译器是非常多才多艺的,通常是绝对最新的,有时甚至支持更多的语言,但是看看他们的网站(OSS Nokalva,Marben 等)。

使用这种技术在完全不同的编程文化(例如“嵌入式”人员和“服务器农民”)的各方之间指定一个接口是非常容易的: asn. 1-file,编码规则,例如 BER 和 UML 交互图。无忧无虑如何实现,让大家用“自己的东西”!对我来说,这种方法非常有效。 Btw. : 在 OSS Nokalva 的网站上,你可以找到至少两本关于 ASN.1的免费下载书籍(一本是 Larmouth 写的,另一本是 Dubuisson 写的)。

恕我直言,大多数其他产品只是试图成为另一个 RPC 短棒发电机,泵入大量的空气进入系列化问题。如果有人需要的话,那就没问题。但是对我来说,它们看起来像是 Sun-RPC 的重新发明(从80年代末开始) ,但是,嘿,那也很好用。

我们刚刚对序列化器做了一个内部研究,这里有一些结果(供我以后参考!)

节约 = 序列化 + RPC 堆栈

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

ASN 1 = 爷爷

ASN.1是由80年代的电信业人士设计的,与最近出现在 CompSci 业人士中的序列化器相比,由于库支持有限,所以使用 尴尬。有两种变体,DER (二进制)编码和 PEM (ascii)编码。两者都很快,但是 DER 更快,并且在两者中更有效率。事实上,ASN.1 DER 可以很容易地跟上(有时甚至击败)在它自己之后设计的 30年了序列化器,这证明了它的良好设计。它非常紧凑,比协议缓冲和节俭都要小,只有阿弗罗打败了它。问题在于要支持大量的库,而现在 Bouncy Castle 似乎是 C #/Java 最好的库。ASN.1是安全和加密系统之王,并且不会消失,所以不要担心“未来的证明”。找个好图书馆。

MessagePack = 包的中间部分

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

常见

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

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

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

这个项目(https://github.com/sidshetye/SerializersCompare)比较了 C # 世界中的重要序列化器。

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!)

微软的 Bond (https://github.com/Microsoft/bond)在性能、功能和文档方面令人印象深刻。然而,到目前为止(2015年2月13日)它并不支持许多目标平台。我只能假设它是因为它是非常新的。目前它支持 python、 c # 和 c + + 。医学界到处都在使用它。我试过了,作为一个 C # 开发人员,使用 bond 比使用 Protobuf 要好,但是我也使用过俭约,我面临的唯一问题是文档,我不得不尝试很多事情来理解事情是如何做的。

有关 Bond 的资源很少,如下所示(https://news.ycombinator.com/item?id=8866694https://news.ycombinator.com/item?id=8866848https://microsoft.github.io/bond/why_bond.html)

为了提高性能,Uber 最近在他们的工程博客上评估了其中的几个库:

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

它们的赢家是什么? 用于压缩的 MessagePack + zlib

我们的目标是找到编码协议和 压缩算法具有最紧凑的最高结果 我们测试了编码协议和压缩算法 2219次匿名优步纽约之旅的组合 City (将文本文件作为 JSON 放入)。

这里的教训是,您的需求驱动了适合您的库。对 Uber 来说,他们不能使用基于 IDL 的协议,因为消息传递是无模式的。这样就排除了很多选择。对他们来说,不仅是原始的编码/解码时间在起作用,还有静止数据的大小。

尺寸测试结果

Size Results

速度成绩

enter image description here