选择序列化框架

时间:2020-03-03 12:11:44

标签: serialization protocol-buffers avro parquet thrift

我正在阅读使用Java序列化的缺点以及使用序列化框架的必要性。有很多框架,例如avro,镶木地板,节俭,protobuff。

问题是什么框架解决选择序列化框架时要考虑的因素以及所有参数。

我想动手实践一个用例,并根据需求比较/选择序列化框架。

有人可以在这个主题上提供帮助吗?

1 个答案:

答案 0 :(得分:2)

有很多因素需要考虑。我将介绍一些重要的内容。

0)架构优先或代码优先

如果您有一个涉及不同语言的项目,那么代码优先方法可能会出现问题。拥有可以序列化的JAVA类都很好,但是如果必须在C中反序列化,可能会很麻烦。

通常,我以架构为先,以防万一。

1)对象间标记

某些序列化产生一个字节流,该字节流使您可以看到一个对象停止在何处而另一个对象在何处开始。其他没有。

因此,如果您有一个消息传输/数据存储区,它将为您分离出几批字节,例如ZeroMQ或数据库字段,则可以使用不标记消息的序列化。示例包括Google协议缓冲区。借助由传输/存储完成的标记,读者可以知道它肯定包含一个对象,并且仅包含一个对象,从而获得一批字节。

如果您的邮件传输/数据存储区未在批字节之间进行标记,例如网络流或文件,那么您要么发明自己的标记,要么使用为您标记的序列化。示例包括ASN.1 BER,XML。

2)规范

这是序列化的属性,这意味着序列化的数据具有其自身的结构。原则上,规范消息的阅读者不必事先知道消息的结构是什么,它可以在读取字节时简单地算出(即使它不知道字段名称)。在您不确定数据来自何处的情况下,这很有用。如果数据不是规范的,则读者必须事先知道对象结构是什么,否则反序列化是不明确的。

规范序列化的示例包括ASN.1 BER,ASN.1规范PER,XML。那些不包含ASN.1 uPER的文件,可能还包含Google协议缓冲区(我可能有错)。

AVRO所做的事情有所不同-数据模式本身就是序列化数据的一部分,因此始终可以从任意数据中重建对象。可以想象,用于这种语言的库在C之类的语言中有些笨拙,而在动态语言中则更好。

3)大小和值受限制。

一些序列化技术允许开发人员对字段的值和数组的大小设置约束。目的是从包含此类约束的模式文件生成的代码将在序列化和反序列化时自动验证对象。

这非常有用-自动完成免费的,由模式驱动的内容检查。找出不合规格的数据非常容易。

这在大型的异构项目(正在使用多种不同的语言)中非常有用,因为关于有效内容和非有效内容的所有真相来源都来自模式,只有模式,并且由自动执行自动执行。生成的代码。开发人员不能忽略/绕过约束,而当约束发生变化时,每个人都会不禁注意到。

示例包括ASN.1(通常由工具集做得很好),XML(通常由免费/廉价工具集不能很好地完成; MS的xsd.exe故意忽略任何此类约束)和JSON(直到对象验证器)。在这三种方法中,ASN.1到目前为止是最详尽的约束语法。它真的非常强大。

没有的示例-Google协议缓冲区。在这方面,GPB非常烦人,因为它根本没有约束。具有值和大小约束的唯一方法是将它们作为注释写在.proto文件中,并希望开发人员阅读并注意它们,或者采用其他非源代码方法。由于GPB非常针对异质系统(实际上支持太阳下的每种语言),因此我认为这是一个非常严重的遗漏,因为必须为项目中使用的每种语言手动编写值/大小验证代码。那是浪费时间。 Google可以在.proto和代码生成器中添加语法元素以支持此操作,而无需完全更改导线孔(全部在自动生成的代码中)。

4)二进制/文本

二进制序列化会更小,并且序列化/反序列化的速度可能会更快一些。文本序列化更易于调试。但是使用二进制序列化可以完成的事情令人惊讶。例如,您可以轻松地将ASN.1解码器添加到Wireshark(使用ASN.1工具从.asn模式文件进行编译),也可以在对程序数据进行有线解码时使用。我应该想到,GPB也有可能。

ASN.1 uPER在带宽受限的情况下非常有用;它自动使用大小/值约束来节省线路上的位。例如,在0到15之间有效的字段仅需要4位,这就是uPER将使用的位。我应该想到,uPER​​在3G,4G和5G等协议中具有很高的功能也并非偶然。这种“最少位”的方法比压缩文本线格式要优雅得多(这是对JSON和XML所做的很多工作,以减少它们的负担)。

5)值

这有点奇怪。在ASN.1中,模式文件既可以定义对象的结构,也可以定义对象的值。使用更好的工具,您最终得到(在C ++,JAVA等源代码中)类,并预定义已经用值填充的该类的对象。

为什么这样有用?好吧,我经常使用它来定义项目常量,并获得约束的限制。例如,假设您在消息中得到一个有效长度为15的数组字段。您可以在字段约束中使用文字15,也可以在约束中引用一个整数对象的值,该整数也可供开发人员使用。在您要遍历该约束的情况下,这真的很方便,因为该循环可以

for (int i = 0; i < ArraySize; i++) {do things with field[i];} // ArraySize is an integer in the auto generated code built from the .asn schema file

很显然,如果需要更改约束,那就太棒了,因为必须更改约束的唯一位置是在架构中,然后进行项目重新编译(使用该位置的每个位置都将使用新值)。更好的是,如果在架构文件中对其进行了重命名,则重新编译会在使用它的对象中的任何地方进行标识(因为使用它的开发人员编写的源代码仍然使用旧名称,现在它是未定义的符号->编译器错误。< / p>

据我所知,只有ASN.1可以做到这一点。然后,只有更昂贵的工具才能从架构文件中实际选择这些元素。有了它,这使得它在大型项目中非常有用,因为从字面上看,所有与数据及其约束以及如何处理数据有关的事物都仅在.asn模式中定义,而在其他任何地方都没有定义。

正如我所说,对于正确的项目类型,我经常使用它。一旦它遍及了整个项目,所节省的时间和风险就非常可观。它也改变了项目的动力。知道整个项目只需要重新编译就可以对模式进行后期更改。因此,在项目后期更改协议会从高风险变为您每天可能会满意的事情。

6)线格式对象类型

某些序列化线格式将以线格式字节数识别对象的类型。这在许多不同类型的对象可能来自一个或多个源的情况下为读者提供了帮助。其他序列化不会。

ASN.1因线路格式而异(它有几种,包括一些二进制的以及XML和JSON)。 ASN.1 BER在其线格式中使用类型,值和长度字段,因此读者有可能预先窥视对象的标签,从而对字节流进行相应的解码。这非常有用。

Google协议缓冲区的功能不尽相同,但是如果.proto中的所有消息类型都捆绑到一个最终的oneof中,那就是只有序列化的每个消息都可以实现相同的效果东西

7)工具成本。

ASN.1工具的范围非常非常昂贵(非常好),再到免费(也不太好)。许多其他工具都是免费的,尽管我发现最好的XML工具(适当注意值/大小约束)也很昂贵。

8)语言覆盖范围

如果您听说过它,那么它可能会被许多不同语言的工具所涵盖。如果没有,那就更少了。

良好的ASN.1商业工具涵盖了C / C ++ / Java / C#。有一些免费的C / C ++,它们的完整性各不相同。

9)质量

如果工具的质量很差,那么采用序列化技术是不好的。

根据我的经验,GPB是很好的(通常会按照它说的做)。商业ASN1工具非常出色,全面超越了GPB的工具集。 AVRO的作品。我听说Capt'n Proto有时会出现问题,但是我自己没有使用过,您必须检查一下。 XML与好的工具一起工作。

10)摘要

如果您不知道,我非常喜欢ASN.1。

GPB还因为其广泛的支持和熟悉度而非常有用,但是我希望Google能够为字段和数组添加值/大小约束,并且还包含一个值符号。如果他们这样做,将有可能使用与ASN.1相同的项目工作流程。如果Google仅添加了这两项功能,我认为GPB可以说是“完整”的了,只需要一个相当于ASN.1的uPER就可以为那些存储空间或带宽很少的人完成。

请注意,其中很大一部分都集中在项目的情况以及技术的实际/快速/成熟程度上。