所有这些都提供二进制序列化,RPC框架和IDL。我对它们与特性(性能,易用性,编程语言支持)之间的主要差异感兴趣。
如果您了解任何其他类似技术,请在答案中提及。
答案 0 :(得分:95)
ASN.1 是ISO / ISE标准。它具有非常易读的源语言和各种后端,包括二进制和人类可读。作为一个国际标准(和那个旧的标准!)源语言有点厨房淡化(大致与大西洋有点湿),但是它非常明确,并且具有相当大的支持。 (如果你足够努力,你可以找到你所命名的任何语言的ASN.1库,如果没有,你可以在FFI中使用很好的C语言库。)它是一种标准化的语言,经过深思熟虑的记录,还提供了一些很好的教程。
节俭不是标准。它最初来自Facebook,后来是开源的,目前是一个顶级的Apache项目。它没有详细记录 - 尤其是教程水平 - 而且对我的(不可否认的简短)一瞥似乎没有添加任何其他的东西,以前的努力还没有(在某些情况下更好)。为了公平起见,它开箱即用的语言数量相当可观,包括一些较为知名的非主流语言。 IDL也像C一样含糊不清。
协议缓冲区不是标准。它是一种Google产品,正在向更广泛的社区发布。它在开箱即用的语言方面有点受限(它只支持C ++,Python和Java),但它确实有很多第三方支持其他语言(质量变化很大)。谷歌使用Protocol Buffers几乎完成了他们所有的工作,所以它是经过实战考验的,经过实战训练的协议(尽管不像ASN.1那样具有战斗力。它比Thrift有更好的文档,但是,作为一个谷歌产品,它很可能是不稳定的(在不断变化的意义上,不是在不可靠的意义上).IDL也是类似C的。
所有上述系统都使用在某种IDL中定义的模式来生成目标语言的代码,然后在编码和解码中使用该目标语言。 Avro没有。 Avro的输入是动态的,它的模式数据在运行时直接用于编码和解码(在处理过程中有一些明显的成本,但对动态语言也有一些明显的好处,并且不需要标记类型等) 。它的架构使用JSON,如果已经有一个JSON库,那么在新语言中支持Avro会更容易管理。同样,与大多数重新设计车轮的协议描述系统一样,Avro也没有标准化。
就个人而言,尽管我与它有着爱/恨的关系,但我可能会将ASN.1用于大多数RPC和消息传输目的,尽管它实际上没有RPC堆栈(你必须制作一个,但是国际奥委会足够简单。)
答案 1 :(得分:37)
我们刚刚对序列化器进行了内部研究,这里有一些结果(我将来也会参考!)
最大的区别是Thrift不仅仅是一个序列化协议,它是一个完整的RPC堆栈,就像现代的SOAP堆栈。因此,在序列化之后,可以通过TCP / IP在计算机之间发送 (但不强制要求)的对象。在SOAP中,您从一个WSDL文档开始,该文档完整地描述了可用的服务(远程方法)和期望的参数/对象。这些对象是通过XML发送的。在Thrift中,.thrift文件完整地描述了可用的方法,期望的参数对象和对象通过一个可用的序列化器(使用Compact Protocol
序列化,这是一种有效的二进制协议,在生产中最受欢迎)。
ASN.1是由电信人员在80年代设计的,并且由于有限的库支持而使用笨拙,与CompSci人员出现的最新序列化器相比。有两种变体,DER(二进制)编码和PEM(ascii)编码。两者都很快,但DER更快,更有效。实际上,ASN.1 DER可以很容易地保持(有时甚至击败)自己设计<30年的序列化器,这证明了它的设计精良。它非常紧凑,比Protocol Buffers和Thrift小,只能被Avro击败。问题在于有很好的库支持,现在Bouncy Castle似乎是C#/ Java的最佳库。 ASN.1在安全和加密系统方面处于领先地位并且不会消失,所以不要担心“未来打样”。得到一个好的图书馆......
这不错,但它既不是最快的,也不是最小的,也不是最好的支持。没有生产理由选择它。
除此之外,它们非常相似。大多数是基本TLV: Type-Length-Value
原则的变体。
协议缓冲区(谷歌发起),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人员已经有something similar。
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!)
答案 2 :(得分: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年代末开始),但是,嘿,这也很好。答案 3 :(得分:11)
从性能角度来看,优步最近在其工程博客上评估了其中几个库:
https://eng.uber.com/trip-data-squeeze/
他们的胜利者? MessagePack + zlib用于压缩
我们的目标是找到编码协议和编码协议的组合 压缩算法以最紧凑的结果最高 速度。我们测试了编码协议和压缩算法 来自优步纽约的2,219个伪随机匿名旅行的组合 City(将文本文件作为JSON放入)。
这里的教训是您的要求驱动哪个库适合您。对于Uber而言,由于他们拥有的消息传递的无模式特性,他们无法使用基于IDL的协议。这消除了一堆选项。同样对他们来说,不仅是原始编码/解码时间发挥作用,而且还有静态数据的大小。
尺寸结果
加速结果
答案 4 :(得分:6)
Microsoft的Bond(https://github.com/Microsoft/bond)在性能,功能和文档方面令人印象深刻。但是,截至目前,它并不支持许多目标平台(2015年3月13日)。我只能假设它是因为它是非常新的。目前它支持python,c#和c ++。它被MS无处不在。我尝试过,对于我来说,使用bond比使用prot更好,但是我也使用了thrift,我遇到的唯一问题是文档,我不得不尝试很多东西来理解事情是如何完成的。< / p>
Bond的资源很少如下(https://news.ycombinator.com/item?id=8866694,https://news.ycombinator.com/item?id=8866848,https://microsoft.github.io/bond/why_bond.html)
答案 5 :(得分:5)
对于性能,一个数据点是jvm-serializers基准 - 它是非常具体的小消息,但如果你在Java平台上可能会有所帮助。我认为一般来说,表现往往不是最重要的区别。另外:永远不要把作者的话当作福音;许多广告声称是假的(例如,msgpack网站有一些可疑的声明;它可能很快,但信息非常粗略,用例不太现实)。
一个很大的区别是是否必须使用模式(PB,至少是Thrift; Avro它可能是可选的; ASN.1我也认为; MsgPack,不一定)。
另外:在我看来,能够使用分层的模块化设计是件好事;也就是说,RPC层不应该规定数据格式,序列化。不幸的是,大多数候选人紧紧捆绑这些。
最后,在选择数据格式时,现在的性能并不排除使用文本格式。有快速的JSON解析器(和非常快的流式xml解析器);当考虑脚本语言的互操作性和易用性时,二进制格式和协议可能不是最佳选择。