本文章转自:乐字节
文章次要解说:Java 罕用序列化框架
获取更多 JAVA 相干材料能够关注公众号《乐字节》发送:999
一 背景介绍
序列化与反序列化是咱们日常数据长久化和网络传输中常常应用的技术,然而目前各种序列化框架让人目迷五色,不分明什么场景到底采纳哪种序列化框架。本文会将业界开源的序列化框架进行比照测试,别离从通用性、易用性、可扩展性、性能和数据类型与 Java 语法反对五方面给出比照测试。
上面别离对 JDK Serializable、FST、Kryo、Protobuf、Thrift、Hession 和 Avro 进行比照测试。
二 序列化框架
1 JDK Serializable
JDK Serializable 是 Java 自带的序列化框架,咱们只须要实现 java.io.Serializable 或 java.io.Externalizable 接口,就能够应用 Java 自带的序列化机制。实现序列化接口只是示意该类可能被序列化 / 反序列化,咱们还须要借助 I / O 操作的 ObjectInputStream 和 ObjectOutputStream 对对象进行序列化和反序列化。
通用性
因为是 Java 内置序列化框架,所以自身是不反对跨语言序列化与反序列化。
易用性
作为 Java 内置序列化框架,无序援用任何内部依赖即可实现序列化工作。然而 JDK Serializable 在应用上相比开源框架难用许多,能够看到下面的编解码应用十分僵硬,须要借助 ByteArrayOutputStream 和 ByteArrayInputStream 才能够残缺字节的转换。
可扩展性
JDK Serializable 中通过 serialVersionUID 管制序列化类的版本,如果序列化与反序列化版本不统一,则会抛出 java.io.InvalidClassException 异样信息,提醒序列化与反序列化 SUID 不统一。
性能
JDK Serializable 是 Java 自带的序列化框架,然而在性能上其实一点不像亲生的。上面测试用例是咱们贯通全文的一个测试实体。
咱们对该测试用例进行 1000 万次序列化,而后计算工夫总和:
同样咱们之后会同其它序列化框架进行比照。
数据类型和语法结构支持性
因为 JDK Serializable 是 Java 语法原生序列化框架,所以根本都可能反对 Java 数据类型和语法。
WeakHashMap 没有实现 Serializable 接口。
2 FST 序列化框架
FST(fast-serialization)是齐全兼容 JDK 序列化协定的 Java 序列化框架,它在序列化速度上能达到 JDK 的 10 倍,序列化后果只有 JDK 的 1 /3。目前 FST 的版本为 2.56,在 2.17 版本之后提供了对 Android 的反对。
通用性
FST 同样是针对 Java 而开发的序列化框架,所以也不存在跨语言个性。
易用性
在易用性上,FST 能够说可能甩 JDK Serializable 几条街,语法极其简洁,FSTConfiguration 封装了大部分办法。
可扩展性
FST 通过 @Version 注解可能反对新增字段与旧的数据流兼容。对于新增的字段都须要通过 @Version 注解标识,没有版本正文意味着版本为 0。
留神:
综合来看,FST 在扩展性下面尽管反对,然而用起来还是比拟繁琐的。
性能
应用 FST 序列化下面的测试用例,序列化后大小为:172,相比 JDK 序列化的 432,将近缩小了 1 /3。上面咱们再看序列化与反序列化的工夫开销。
数据类型和语法结构支持性
FST 是基于 JDK 序列化框架而进行开发的,所以在数据类型和语法上和 Java 支持性统一。
3 Kryo 序列化框架
Kryo 一个疾速无效的 Java 二进制序列化框架,它依赖底层 ASM 库用于字节码生成,因而有比拟好的运行速度。Kryo 的指标就是提供一个序列化速度快、后果体积小、API 简略易用的序列化框架。Kryo 反对主动深 / 浅拷贝,它是间接通过对象 -> 对象的深度拷贝,而不是对象 -> 字节 -> 对象的过程。
通用性
首先 Kryo 官网说本人是一款 Java 二进制序列化框架,其次在网上搜了一遍没有看到 Kryo 的跨语言应用,只是一些文章提及了跨语言应用非常复杂,然而没有找到其它语言的相干实现。
易用性
在应用形式上 Kryo 提供的 API 也是十分简洁易用,Input 和 Output 封装了你简直可能想到的所有流操作。Kryo 提供了丰盛的灵便配置,比方自定义序列化器、设置默认序列化器等等,这些配置应用起来还是比拟吃力的。
可扩展性
Kryo 默认序列化器 FiledSerializer 是不反对字段扩大的,如果想要应用扩大序列化器则须要配置其它默认序列化器。
性能
应用 Kryo 测试下面的测试用例,Kryo 序列化后的字节大小为 172,和 FST 未经优化的大小统一。工夫开销如下:
咱们同样敞开循环援用配置和预注册序列化类,序列化后的字节大小为 120,因为这时候类序列化的标识是应用的数字,而不是类全名。应用的是工夫开销如下:
数据类型和语法结构支持性
Kryo 对于序列化类的根本要求就是须要含有无参构造函数,因为反序列化过程中须要应用无参构造函数创建对象。
4 Protocol buffer
Protocol buffer 是一种语言中立、平台无关、可扩大的序列化框架。Protocol buffer 相较于后面几种序列化框架而言,它是须要事后定义 Schema 的。
通用性
protobuf 设计之初的指标就是可能设计一款与语言无关的序列化框架,它目前反对了 Java、Python、C++、Go、C# 等,并且很多其它语言都提供了第三方包。所以在通用性上,protobuf 是十分给力的。
易用性
protobuf 须要应用 IDL 来定义 Schema 形容文件,定义完形容文件后,咱们能够间接应用 protoc 来间接生成序列化与反序列化代码。所以,在应用上只须要简略编写形容文件,就能够应用 protobuf 了。
可扩展性
可扩展性同样是 protobuf 设计之初的指标之一,咱们能够十分轻松的在.proto 文件进行批改。
新增字段:对于新增字段,咱们肯定要保障新增字段要有对应的默认值,这样才可能与旧代码交互。相应的新协定生成的音讯,能够被旧协定解析。
删除字段:删除字段须要留神的是,对应的字段、标签不可能在后续更新中应用。为了防止谬误,咱们能够通过 reserved 躲避带哦。
protobuf 在数据兼容性上也十分敌对,int32、unit32、int64、unit64、bool 是齐全兼容的,所以咱们能够依据须要批改其类型。
通过下面来看,protobuf 在扩展性上做了很多,可能很敌对的反对协定扩大。
性能
咱们同样应用下面的实例来进行性能测试,应用 protobuf 序列化后的字节大小为 192,上面是对应的工夫开销。
能够看出 protobuf 的反序列化性能要比 FST、Kryo 差一些。
数据类型和语法结构反对
Protobuf 应用 IDL 定义 Schema 所以不反对定义 Java 办法,上面序列化变量的测试:
注:List、Set、Queue 通过 protobuf repeated 定义测试的。只有实现 Iterable 接口的类都能够应用 repeated 列表。
5 Thrift 序列化框架
Thrift 是由 Facebook 实现的一种高效的、反对多种语言的近程服务调用框架,即 RPC(Remote Procedure Call)。起初 Facebook 将 Thrift 开源到 Apache。能够看到 Thrift 是一个 RPC 框架,然而因为 Thrift 提供了多语言之间的 RPC 服务,所以很多时候被用于序列化中。
应用 Thrift 实现序列化次要分为三步,创立 thrift IDL 文件、编译生成 Java 代码、应用 TSerializer 和 TDeserializer 进行序列化和反序列化。
通用性
Thrift 和 protobuf 相似,都须要应用 IDL 定义形容文件,这是目前实现跨语言序列化 /RPC 的一种无效形式。Thrift 目前反对 C++、Java、Python、PHP、Ruby、Erlang、Perl、Haskell、C#、Cocoa、JavaScript、Node.js、Smalltalk、OCaml、Delphi 等语言,所以能够看到 Thrift 具备很强的通用性。
易用性
Thrift 在易用性上和 protobuf 相似,都须要通过三步:应用 IDL 编写 thrift 文件、编译生成 Java 代码和调用序列化与反序列化办法。protobuf 在生成类中曾经内置了序列化与反序列化办法,而 Thrift 须要独自调用内置序列化器来进行编解码。
可扩展性
Thrift 反对字段扩大,在扩大字段过程中须要留神以下问题:
性能
下面的测试用例,应用 Thrift 序列化后的字节大小为:257,上面是对应的序列化工夫与反序列化工夫开销:
Thrift 在序列化和反序列化的工夫开销总和上和 protobuf 差不多,protobuf 在序列化工夫上更占优势,而 Thrift 在反序列化上有本人的劣势。
数据类型和语法结构反对
数据类型反对:因为 Thrift 应用 IDL 来定义序列化类,所以可能反对的数据类型就是 Thrift 数据类型。Thrift 所可能反对的 Java 数据类型:
Thrift 同样不反对定义 Java 办法。
6 Hessian 序列化框架
Hessian 是 caucho 公司开发的轻量级 RPC(Remote Procedure Call)框架,它应用 HTTP 协定传输,应用 Hessian 二进制序列化。
Hessian 因为其反对跨语言、高效的二进制序列化协定,被常常用于序列化框架应用。Hessian 序列化协定分为 Hessian1.0 和 Hessian2.0,Hessian2.0 协定对序列化过程进行了优化 (优化内容待看),在性能上相较 Hessian1.0 有显著晋升。
应用 Hessian 序列化非常简单,只须要通过 HessianInput 和 HessianOutput 即可实现对象的序列化,上面是 Hessian 序列化的 Demo:
通用性
Hessian 与 Protobuf、Thrift 一样,反对跨语言 RPC 通信。Hessian 相比其它跨语言 PRC 框架的一个次要劣势在于,它不是采纳 IDL 来定义数据和服务,而是通过自描述来实现服务的定义。目前 Hessian 曾经实现了语言包含:Java、Flash/Flex、Python、C++、.Net/C#、D、Erlang、PHP、Ruby、Object-C。
易用性
相较于 Protobuf 和 Thrift,因为 Hessian 不须要通过 IDL 来定义数据和服务,对于序列化的数据只须要实现 Serializable 接口即可,所以应用上相比 Protobuf 和 Thrift 更加容易。
可扩展性
Hession 序列化类尽管须要实现 Serializable 接口,然而它并不受 serialVersionUID 影响,可能轻松反对字段扩大。
性能
应用 Hessian1.0 协定序列化下面的测试用例,序列化后果大小为 277。应用 Hessian2.0 序列化协定,序列化后果大小为 178。
序列化化与反序列化的工夫开销如下:
能够看到 Hessian1.0 的无论在序列化后体积大小,还是在序列化、反序列化工夫上都比 Hessian2.0 相差很远。
数据类型和语法结构反对
因为 Hession 应用 Java 自描述序列化类,所以 Java 原生数据类型、汇合类、自定义类、枚举等根本都可能反对(SynchronousQueue 不反对),Java 语法结构也可能很好的反对。
7 Avro 序列化框架
Avro 是一个数据序列化框架。它是 Apache Hadoop 下的一个子项目,由 Doug Cutting 主导 Hadoop 过程中开发的数据序列化框架。Avro 在设计之初就用于反对数据密集型利用,很适宜近程或本地大规模数据交换和存储。
通用性
Avro 通过 Schema 定义数据结构,目前反对 Java、C、C++、C#、Python、PHP 和 Ruby 语言,所以在这些语言之间 Avro 具备很好的通用性。
易用性
Avro 对于动静语言无需生成代码,但对于 Java 这类动态语言,还是须要应用 avro-tools.jar 来编译生成 Java 代码。在 Schema 编写上,个人感觉相比 Thrift、Protobuf 更加简单。
可扩展性
性能
应用 Avro 生成代码序列化之后的后果为:111。上面是应用 Avro 序列化的工夫开销:
数据类型和语法结构反对
Avro 须要应用 Avro 所反对的数据类型来编写 Schema 信息,所以可能反对的 Java 数据类型即为 Avro 所反对的数据类型。Avro 反对数据类型有:根底类型(null、boolean、int、long、float、double、bytes、string),简单数据类型(Record、Enum、Array、Map、Union、Fixed)。
Avro 主动生成代码,或者间接应用 Schema,不能反对在序列化类中定义 java 办法。
三 总结
1 通用性
上面是从通用性上比照各个序列化框架,能够看出 Protobuf 在通用上是最佳的,可能反对多种支流变成语言。
2 易用性
上面是从 API 应用的易用性下面来比照各个序列化框架,能够说除了 JDK Serializer 外的序列化框架都提供了不错 API 应用形式。
3 可扩展性
上面是各个序列化框架的可扩展性比照,能够看到 Protobuf 的可扩展性是最不便、天然的。其它序列化框架都须要一些配置、注解等操作。
4 性能
序列化大小比照
比照各个序列化框架序列化后的数据大小如下,能够看出 kryo preregister(事后注册序列化类)和 Avro 序列化后果都很不错。所以,如果在序列化大小上有需要,能够抉择 Kryo 或 Avro。
序列化工夫开销比照
上面是序列化与反序列化的工夫开销,kryo preregister 和 fst preregister 都能提供优异的性能,其中 fst pre 序列化工夫就最佳,而 kryo pre 在序列化和反序列化工夫开销上基本一致。所以,如果序列化工夫是次要的思考指标,能够抉择 Kryo 或 FST,都能提供不错的性能体验。
5 数据类型和语法结构反对
各序列化框架对 Java 数据类型反对的比照:
注:汇合类型测试根本笼罩了所有对应的实现类。
上面依据测试总结了以上序列化框架所能反对的数据类型、语法。
因为 Protobuf、Thrift 是 IDL 定义类文件,而后应用各自的编译器生成 Java 代码。IDL 没有提供定义 staic 外部类、非 static 外部类等语法,所以这些性能无奈测试。
感激大家的认同与反对,小编会继续转发《乐字节》优质文章