十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
通用性:通用性是指序列化框架是否支持跨语言、跨平台。
成都创新互联公司主营儋州网站建设的网络公司,主营网站建设方案,APP应用开发,儋州h5微信小程序定制开发搭建,儋州网站营销推广欢迎儋州等地区企业咨询易用性:易用性是指序列化框架是否便于使用、调试,会影响开发效率。
可扩展性:随着业务的发展,传输实体可能会发生变化,但是旧实体有可能还会被使用。这时候就需要考虑所选择的序列化框架是否具有良好的扩展性。
性能:序列化性能主要包括时间开销和空间开销。序列化的数据通常用于持久化或网络传输,所以其大小是一个重要的指标。而编解码时间同样是影响序列化协议选择的重要指标,因为如今的系统都在追求高性能。
Java数据类型和语法支持:不同序列化框架所能够支持的数据类型以及语法结构是不同的。这里我们要对Java的数据类型和语法特性进行测试,来看看不同序列化框架对Java数据类型和语法结构的支持度。
框架 | JDK序列化 | FST | Kryo | Protobuf(注2) | Thift | Hession | Avro |
---|---|---|---|---|---|---|---|
通用性 | 不支持 | 不支持 | 支持但非常复杂 | 非常通用 | 非常通用 | 支持跨语言RPC通信 | 非常通用 |
易用性 | 略复杂 | 语法简洁 | 语法简洁 | 比较简单 | 比较简单 | 非常简单 | 略复杂 |
可扩展性 | 可扩展(注1) | 略复杂 | 支持 | 友好支持 | 友好支持 | 友好支持 | 略复杂 |
性能 | 耗时久,字节多 | 速度快,字节少 | 速度快,字节少 | 略低于前FST,Kryo | 和Protobuf类型 | 速度快,字节少 | 速度快,字节少 |
数据类型和语法支持 | 基本支持 | 基本支持 | 基本支持 | 不支持定义Java方法 | 不支持定义Java方法 | 基本支持 | 不支持定义Java方法 |
序列化框架 | 通用性 |
---|---|
JDK Serializer | 使用语法过于生硬 |
FST | 使用简洁,FSTConfiguration提供了序列化与反序列化的方法 |
Kryo | 使用简洁,Input/Output封装了几乎所有能有需要的流方法 |
Protocol buffer | 稍微复杂。需要编写所需序列化类的proto文件,然后编译生成Java代码。但是自动生成Java类,包含了序列化与反序列化方法 |
Thrift | 稍微复杂。需要编写所需的序列化类的thrift文件,然后编译生成Java代码。然后通过TSerializer和TDserializer进行序列化与反序列化 |
Hessian | 使用简单,在跨语言的基础上不需要使用IDL |
Avro | 使用较复杂。相较于Protobuf和Thrift来说,对于一些静态语言无序生成代码。但是对于Java来一般还需要生成代码,并且Avro提供的API不是很友好 |
序列化框架 | 易用性 |
---|---|
JDK Serializer | 使用语法过于生硬 |
FST | 使用简洁,FSTConfiguration提供了序列化与反序列化的方法 |
Kryo | 使用简洁,Input/Output封装了几乎所有能有需要的流方法 |
Protocol buffer | 稍微复杂。需要编写所需序列化类的proto文件,然后编译生成Java代码。但是自动生成Java类,包含了序列化与反序列化方法 |
Thrift | 稍微复杂。需要编写所需的序列化类的thrift文件,然后编译生成Java代码。然后通过TSerializer和TDserializer进行序列化与反序列化 |
Hessian | 使用简单,在跨语言的基础上不需要使用IDL |
Avro | 使用较复杂。相较于Protobuf和Thrift来说,对于一些静态语言无序生成代码。但是对于Java来一般还需要生成代码,并且Avro提供的API不是很友好 |
序列化框架 | 可扩展性 |
---|---|
JDK Serializer | 自定义serialVersionUID,保证序列化前后VUID一致即可 |
FST | 通过@Version控制版本,新增字段需要修改Version版本 |
Kryo | 默认序列化器不支持字段扩展,需要修改默认序列化器或自己实现序列化器 |
Protocol buffer | 支持字段扩展,只要保证新增id标识没有使用过即可 |
Thrift | 支持字段扩展。新增字段为required类型时,需要设置默认值 |
Hessian | 支持字段扩展 |
Avro | 支持字段扩展。注意需要为字段设置默认值 |
序列化大小对比
对比各个序列化框架序列化后的数据大小如下,可以看出kryo preregister(预先注册序列化类)和Avro序列化结果都很不错。所以,如果在序列化大小上有需求,可以选择Kryo或Avro。
序列化时间开销对比
序列化与反序列化的时间开销,kryo preregister和fst preregister都能提供优异的性能,其中fst pre序列化时间就最佳,而kryo pre在序列化和反序列化时间开销上基本一致。所以,如果序列化时间是主要的考虑指标,可以选择Kryo或FST,都能提供不错的性能体验。
JDK Serializable中通过serialVersionUID控制序列化类的版本,如果序列化与反序列化版本不一致,则会抛出java.io.InvalidClassException异常信息,提示序列化与反序列化SUID不一致。
java.io.InvalidClassException: com.yjz.serialization.java.UserInfo; local class incompatible: stream classdesc serialVersionUID = -5548195544707231683, local class serialVersionUID = -5194320341014913710
上面这种情况,是由于我们没有定义serialVersionUID,而是由JDK自动hash生成的,所以序列化与反序列化前后结果不一致。
但是我们可以通过自定义serialVersionUID方式来规避掉这种情况(序列化前后都是使用定义的serialVersionUID),这样JDK Serializable就可以支持字段扩展了。
private static final long serialVersionUID = 1L;
Protocol buffer是一种语言中立、平台无关、可扩展的序列化框架。Protocol buffer相较于前面几种序列化框架而言,它是需要预先定义Schema的。
下面是使用Protobuf的Demo:
(1)编写proto描述文件:
syntax = "proto3";
option java_package = "com.yjz.serialization.protobuf3";
message MessageInfo
{
string username = 1;
string password = 2;
int32 age = 3;
map params = 4;
}
(2)生成Java代码:
protoc --java_out=./src/main/java message.proto
(3)生成的Java代码,已经自带了编解码方法:
//编码
byte[] bytes = MessageInfo.toByteArray()
//解码
MessageInfo messageInfo = Message.MessageInfo.parseFrom(bytes);