首页 文章

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

提问于
浏览
113

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

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

6 回答

  • 9

    ASN.1 是ISO / ISE标准 . 它具有非常易读的源语言和各种后端,包括二进制和人类可读 . 作为一个国际标准(和那个旧的标准!)源语言有点厨房淡化(大致与大西洋有点湿),但是它非常明确,并且具有相当大的支持 . (如果你足够努力,你可以找到你所命名的任何语言的ASN.1库,如果没有,你可以在FFI中使用很好的C语言库 . )它是一种标准化的语言,经过深思熟虑的记录,还提供了一些很好的教程 .

    Thrift 不是标准 . 它最初来自Facebook,后来是开源的,目前是一个顶级的Apache项目 . 它没有详细记录 - 特别是教程水平 - 以及我的(不可否认的简短)一瞥已经没有(并且在某些情况下更好) . 为了公平起见,它开箱即用的语言数量相当可观,包括一些较为知名的非主流语言 . IDL也模糊地像C一样 .

    Protocol Buffers 不是标准 . 它是一种Google产品,正在向更广泛的社区发布 . 它在开箱即用的语言方面有点受限(它只支持C,Python和Java),但它确实有很多第三方支持其他语言(质量变化很大) . 谷歌使用Protocol Buffers几乎完成了他们所有的工作,所以它是经过实战考验的,经过实战训练的协议(尽管不像ASN.1那样具有战斗力 . 它比Thrift有更好的文档,但是,作为一个谷歌产品,它很可能是不稳定的(在不断变化的意义上,不是不可靠的意义上).IDL也是类似C的 .

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

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

  • 6

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

    Thrift =序列化RPC堆栈

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

    ASN.1 =大爸爸

    ASN.1是由80年代的电信人员设计的,由于有限的库支持而与CompSci人员出现的最新序列化器相比,使用起来很尴尬 . 有两种变体,DER(二进制)编码和PEM(ascii)编码 . 两者都很快,但DER更快,更有效 . 实际上,ASN.1 DER可以很容易地保持(有时甚至击败)30年后设计的序列化器,这证明它非常紧凑,比协议缓冲器和Thrift小,只能被Avro击败 . 问题在于拥有优秀的图书馆以支持现在的Bouncy Castle似乎是C#/ Java的最佳选择 . ASN.1是安全和加密系统的王者,并且不会担心'future proofing' . 得到一个好的图书馆......

    MessagePack =包中间

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

    普通

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

    协议缓冲区(Google发起),Avro(基于Apache,用于Hadoop),Thrift(Facebook发起,现在是Apache项目)和ASN.1(电信发起)都涉及一定程度的代码生成,您首先在序列化程序中表达数据 - 特定格式,然后序列化程序"compiler"将通过 code-gen 阶段为您的语言生成源代码 . 然后,您的应用程序源将这些 code-gen 类用于IO . 请注意,某些实现(例如:Microsoft 's Avro library or Marc Gavel' s ProtoBuf.NET)允许您直接装饰您的应用程序级POCO / POJO对象,然后库直接使用那些装饰类而不是任何代码's classes. We' ve看到此提供的提升性能,因为它消除了对象复制阶段(从应用程序级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!)
    
  • 11

    关于ASN.1的一个重要的事情是,这是为 specification 而不是实现而设计的 . 因此,它非常擅长隐藏/忽略任何"real"编程语言中的实现细节 .

    它的作用是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年代末开始),但是,嘿,这也很好 .

  • 5

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

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

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

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

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

    Size Results

    Size Results

    Speed Results

    enter image description here

  • 92

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

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

  • 36

    对于性能,一个数据点是jvm-serializers基准 - 它是's quite specific, small messages, but might help if you are on Java platform. I think performance in general will often not be the most important difference. Also: NEVER take authors'单词作为福音;许多广告声称是虚假的(例如,msgpack网站有一些可疑的声明;它可能很快,但信息非常粗略,用例不太现实) .

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

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

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

相关问题