序列化和反序列化

目录

序列化和反序列化 - 美团技术团队 (meituan.com)

定义

序列化协议特性

通用性:

强健性/鲁棒性:

可调试性/可读性:

性能:

可扩展性/兼容性:

安全性/访问限制:

序列化和反序列化的组件

IDL接口描述语言:

IDL Compiler编译器:

Stub/Skeleton Lib:

Client/Server:

底层协议栈和互联网:

序列化组件与数据库访问组件的对比:

几种常见的序列化和反序列化协议

XML&SOAP

典型应用场景和非应用场景:

JSON

Thrift

Protobuf

Avro

Benchmark以及选型建议

选型建议




序列化和反序列化 - 美团技术团队 (meituan.com)

定义

互联通讯的双方需要采用约定的协议,序列化和反序列化属于通讯协议的一部分。

        通讯协议采用的是分层模型,OSI七层网络模型中表示层的主要功能就是把应用层的对象转换成一段连续的二进制串,或者反过来把二进制串转化成应用层对象-这个功能就是序列化和反序列化。对应在TCP/IP网络模型中就是应用层。

  • 序列化: 将数据结构或对象转换成二进制串的过程
  • 反序列化:将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程

序列化协议特性

每种序列化协议都有优点和缺点,它们在设计之初有自己独特的应用场景。

通用性:

1. 技术层面,序列化协议是否支持跨平台、跨语言;

2. 流行程度,序列化和反序列化需要多方参与,流行度搞的肯定更稳定、更成熟;

强健性/鲁棒性:

以下两个方面的原因会导致协议不够强健:

1. 成熟度不够;

2. 语言/平台的不公平性。

可调试性/可读性:

序列化和反序列化的数据正确性和业务正确性的调试往往需要很长的时间,良好的调试机制会大大提高开发效率。

在跨公司调试过程中:由于支持不及时,或者访问权限问题回导致调试困难,因为不知道是发送方有问题还是接收方有问题,两者之间也不一定愿意共享权限。

如果序列化后的数据人眼可读,会大大提高调试效率。XML和JSON就具有人眼可读的优点。

性能:

性能包括两个方面,时间复杂度和空间复杂度:

第一、空间开销(Verbosity), 序列化需要在原有的数据上加上描述字段,以为反序列化解析之用。如果序列化过程引入的额外开销过高,可能会导致过大的网络,磁盘等各方面的压力。对于海量分布式存储系统,数据量往往以TB为单位,巨大的的额外空间开销意味着高昂的成本。

第二、时间开销(Complexity),复杂的序列化协议会导致较长的解析时间,这可能会使得序列化和反序列化阶段成为整个系统的瓶颈。

可扩展性/兼容性:

业务系统需求的更新周期快,如果序列化协议具有良好的可扩展性,支持自动增加新的业务字段,而不影响老的服务,这将大大提供系统的灵活度。

安全性/访问限制:

安全性的考虑往往发生在跨局域网访问的场景,如果通讯发生在跨公司之间或者跨机房,出于安全的考虑,对于跨局域网的访问往往被限制为基于HTTP/HTTPS的80和443端口

如果使用的序列化协议没有兼容而成熟的HTTP传输层框架支持,可能会导致以下三种结果之一:

第一、因为访问限制而降低服务可用性。 第二、被迫重新实现安全协议而导致实施成本大大提高。 第三、开放更多的防火墙端口和协议访问,而牺牲安全性。

序列化和反序列化的组件

典型的序列化和反序列化往往需要以下组件:

IDL接口描述语言:

参与通信的双方需要对通讯的内容做相关约定(与语言平台无关) 采用IDL撰写的协议约定称之为IDL文件。

IDL Compiler编译器:

IDL文件中约定的内容为了在各语言和平台可见,将IDL文件转换成各语言对应的动态库。

Stub/Skeleton Lib:

负责序列化和反序列化的工作代码。

Stub是一段部署在分布式系统客户端的代码,一方面接收应用层的参数,并对其序列化后通过底层协议栈发送到服务端,另一方面接收服务端序列化后的结果数据,反序列化后交给客户端应用层

Skeleton部署在服务端,其功能与Stub相反,从传输层接收序列化参数,反序列化后交给服务端应用层,并将应用层的执行结果序列化后最终传送给客户端Stub。

Client/Server:

指的是应用层程序代码,他们面对的是IDL所生存的特定语言的class或struct。

底层协议栈和互联网:

序列化之后的数据通过底层的传输层、网络层、链路层以及物理层协议转换成数字信号在互联网中传递。

序列化组件与数据库访问组件的对比:

几种常见的序列化和反序列化协议

XML&SOAP

XML是一种常用的序列化和反序列化协议,具有跨机器,跨语言等优点。冗长而复杂。

SOAP(Simple Object Access protocol) 是一种被广泛应用的,基于XML为序列化和反序列化协议的结构化消息传递协议。SOAP虽然可以支持多种传输层协议,不过SOAP最常见的使用方式还是XML+HTTP。SOAP具有安全、可扩展、跨语言、跨平台并支持多种传输层协议。

典型应用场景和非应用场景:

SOAP协议:基于HTTP的传输协议使得其在穿越防火墙时具有良好安全特性,XML所具有的人眼可读(Human-readable)特性使得其具有出众的可调试性,互联网带宽的日益剧增也大大弥补了其空间开销大(Verbose)的缺点。对于在公司之间传输数据量相对小或者实时性要求相对低(例如秒级别)的服务是一个好的选择。(XML时间空间开销都比较大)

JSON

起源于弱类型语言Javascript,本质是就是采用”Attribute-value”的方式来描述对象。

优点:

1. 这种Associative array格式非常符合工程师对对象的理解。

2. 它保持了XML的人眼可读(Human-readable)的优点。

3. 相对于XML而言,序列化后的数据更加简洁。XML所产生序列化之后文件的大小接近JSON的两倍。

4.与XML相比,其协议比较简单,解析速度比较快

5.具有良好的可扩展性和兼容性。

采用JSON进行序列化不需要IDL:由于Associative array和一般语言里面的class太像了,他们之间形成了一一对应关系,这就使得我们可以采用一套标准的代码进行相应的转化。对于自身支持Associative array的弱类型语言,语言自身就具备操作JSON序列化后的数据的能力;对于Java这强类型语言,可以采用反射的方式统一解决,例如Google提供的Gson。

        总的来说,采用JSON进行序列化的额外空间开销比较大,对于大数据量服务或持久化,这意味着巨大的内存和磁盘开销,这种场景不适合。没有统一可用的IDL降低了对参与方的约束,实际操作中往往只能采用文档方式来进行约定,这可能会给调试带来一些不便,延长开发周期。 由于JSON在一些语言中的序列化和反序列化需要采用反射机制,所以在性能要求为ms级别,不建议使用。 

Thrift

Thrift是Facebook开源提供的一个高性能,轻量级RPC服务框架,其产生正是为了满足当前大数据量、分布式、跨语言、跨平台数据通讯的需求。 

但是由于Thrift的序列化被嵌入到Thrift框架里面,Thrift框架本身并没有透出序列化和反序列化接口,这导致其很难和其他传输层协议共同使用(例如HTTP)

Protobuf

Protobuf具备了优秀的序列化协议的所需的众多典型特征:

1、标准的IDL和IDL编译器,这使得其对工程师非常友好。

2、序列化数据非常简洁,紧凑,与XML相比,其序列化之后的数据量约为1/3到1/10。

3、解析速度非常快,比对应的XML快约20-100倍。

4、提供了非常友好的动态库,使用非常简介,反序列化只需要一行代码。

展示层协议,可以和各种传输层协议一起使用空间开销小以及高解析性能是其亮点,Protobuf与传输层无关,采用HTTP具有良好的跨防火墙的访问属性,所以Protobuf也适用于公司间对性能要求比较高的场景。由于其解析性能高,序列化后数据量相对少,非常适合应用层对象的持久化场景。

Avro

解决了JSON的冗长和没有IDL的问题,Avro提供两种序列化格式:JSON格式或者Binary格式。Binary格式在空间开销和解析性能方面可以和Protobuf媲美,JSON格式方便测试阶段的调试。

Benchmark以及选型建议

时间复杂度和空间复杂度:

选型建议

以上描述的五种序列化和反序列化协议都各自具有相应的特点,适用于不同的场景:

1、对于公司间的系统调用,如果性能要求在100ms以上的服务,基于XML的SOAP协议是一个值得考虑的方案。

2、基于Web browser的Ajax,以及Mobile app与服务端之间的通讯,JSON协议是首选。对于性能要求不太高,或者以动态类型语言为主,或者传输数据载荷很小的的运用场景,JSON也是非常不错的选择。

3、对于调试环境比较恶劣的场景,采用JSON或XML能够极大的提高调试效率,降低系统开发成本。

4、当对性能和简洁性有极高要求的场景,Protobuf,Thrift,Avro之间具有一定的竞争关系。

5、对于T级别的数据的持久化应用场景,Protobuf和Avro是首要选择。如果持久化后的数据存储在Hadoop子项目里,Avro会是更好的选择。

6、由于Avro的设计理念偏向于动态类型语言,对于动态语言为主的应用场景,Avro是更好的选择。

7、对于持久层非Hadoop项目,以静态类型语言为主的应用场景,Protobuf会更符合静态类型语言工程师的开发习惯。

8、如果需要提供一个完整的RPC解决方案,Thrift是一个好的选择。

9、如果序列化之后需要支持不同的传输层协议,或者需要跨防火墙访问的高性能场景,Protobuf可以优先考虑。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值