编解码技术及序列化框架介绍

###介绍

什么是序列化

编码(encode)称之为序列化(serialization),它将对象序列化为字节数组,用于网络传输、数据持久化或者其它用途。

什么是反序列化

解码(Decode)/反序列化(deserialization)把从网络、磁盘等读取的字节数组还原成原始对象(通常是原始对象的拷贝),以方便后续的业务逻辑操作。

用途

进行远程跨进程服务调用时(例如RPC调用),需要使用特定的编解码技术,对需要进行网络传输的对象做编码或者解码,以便完成远程调用。

常见的编解码框架

Java序列化

  • 特点

    1、java默认提供的序列化机制

    2、使用简单、开发门槛低

    3、不支持跨语言:由于Java序列化技术是Java语言内部的私有协议,其它语言并不支持,对于用户来说它完全是黑盒,序列后的字节数组,别的语言无法进行反序列化。

    4、序列化后的字节码太大

    5、序列化效率差

Google的Protobuf

Protobuf全称Google Protocol Buffers,它由谷歌开源而来,在谷歌内部久经考验。它将数据结构以.proto文件进行描述,通过代码生成工具可以生成对应数据结构的POJO对象和Protobuf相关的方法和属性

  • 特点:

    1、官方支持C++、Java和Python三种语言

    2、结构化数据存储格式(XML、JSON等)

    3、语言无关、平台无关

    4、高效的编解码性能

Google的Protostuff

它基于 Protobuf 序列化框架,面向 POJO,无需编写 .proto 文件

  • 特点:

    1、速度快

    2、需要静态编译

Apache的Thrift

Thrift源于Facebook,在2007年Facebook将Thrift作为一个开源项目提交给Apache基金会。对于当时的Facebook来说,创造Thrift是为了解决Facebook各系统间大数据量的传输通信以及系统之间语言环境不同需要跨平台的特性,因此Thrift可以支持多种程序语言,如C++、C#、Cocoa、Erlang、Haskell、Java、Ocami、Perl、PHP、Python、Ruby和Smalltalk。

在多种不同的语言之间通信,Thrift可以作为高性能的通信中间件使用,它支持数据(对象)序列化和多种类型的RPC服务。Thrift适用于静态的数据交换,需要先确定好它的数据结构,当数据结构发生变化时,必须重新编辑IDL文件,生成代码和编译,这一点跟其他IDL工具相比可以视为是Thrift的弱项。Thrift适用于搭建大型数据交换及存储的通用工具,对于大型系统中的内部数据传输,相对于JSON和XML在性能和传输大小上都有明显的优势。

  • Thrift主要由5部分组成

    1、语言系统以及IDL编译器:负责由用户给定的IDL文件生成相应语言的接口代码

    2、TProtocol:RPC的协议层,可以选择多种不同的对象序列化方式,如JSON和Binary

    3、TTransport:RPC的传输层,同样可以选择不同的传输层实现,如socket、NIO、MemoryBuffer等

    4、TProcessor:作为协议层和用户提供的服务实现之间的纽带,负责调用服务实现的接口

    5、TServer:聚合TProtocol、TTransport和TProcessor等对象

  • Thrift支持三种比较典型的编解码方式

    1、通用的二进制编解码

    2、压缩二进制编解码

    3、优化的可选字段压缩编解码

Kryo

它使一个快速高效的Java对象序列化框架

  • 特点

    1、速度快

    2、支持互相引用,比如类A引用类B,类B引用类A,可以正确地反序列化。(需将reference选项打开)

    3、支持多个引用同一个对象,比如多个类引用了同一个对象O,只会保存一份O的数据。

    4、支持一些有用的注解,如@Tag,@Optional。

    5、支持忽略指定的字段。

    6、支持null

    7、代码入侵少

    8、代码比较简法

  • 缺点

    1、跨语言支持较复杂

示例代码如下:

Kryo kryo = new Kryo();
// ...
Output output = new Output(new FileOutputStream("file.txt"));
SomeClass someObject = ...
kryo.writeObject(output, someObject);
output.close();
// ...
Input input = new Input(new FileInputStream("file.txt"));
SomeClass someObject = kryo.readObject(input, SomeClass.class);
input.close();
----EOF-----

Categories: java Tags: java