最后更新:2022-07-29 05:52:09 手机定位技术交流文章
在设计或重构系统的过程中,特别是在设计分布式、大数据量系统里面,序列化选型是一个重要环节,因为序列化协议影响系统的通用性、健壮性、安全性,是否易于调试、是否便于扩展。
理论和实践的序列部分,理论部分描述了序列是什么和该做什么.不感兴趣于实现(因为没有考虑具体实现,因此,我们当然不考虑优缺点并应用场景;实际部分描述了如何完成序列操作,物体如何表达自己,也就是说,从理论世界带进现实世界。序列理论部分与设计相等,实践部分与实现相等.
理论
序列理论的三个方面
序列化定义;
通信协议中的序列化状况;
序列化组件
1.序列问题如何产生(序列的定义)
互联网的发展导致了机器间通信的需要,机器之间的通信需要通信协议.通信协议还考虑如何显示和传输数据。序列是通信协议的一部分,它涉及数据的表示。OSI七层协议模型中的展现层(Presentation Layer)的主要功能是把对象转换成一段连续的二进制串,或者将二进制字符串转换为对象,即序列和逆序列。
因此,序列和反序列的定义是:
序列:将数据结构或对象转换为二进制字符串
逆序列:将在序列过程中生成的二进制字符串转换为数据结构或对象
注:只要可以传输到通信的另一端,例如uTF-8字符串,转换为二进制不一定需要。
2.通信协议中的顺序定位
OSI七层协议模型,序列化位于展示层(Presentation Layer)
在TCP/IP协议中,序列位于应用程序层。
3.序列和反序列组件
完整的序列协议包括以下组件:
IDL(Interface description language)。参与通讯的各方需要对通讯的内容做相关约定。由于与语言和平台无关的原因,该公约需要使用与编程语言或平台无关的语言来描述。该语言被称为接口描述语言(IDL)。一个由IDL编写的协议叫做IDL文件。
IDL Compiler:IDL文件中的约定需要一个编译器,将IDL文件转换成各编程语言的动态库。
Stub/Skeleton Lib:序列和逆序列的代码。Stub是一个向客户部署的代码,一方面,它接收到应用程序层的参数,然后通过下层协议堆栈发送到服务端,然后在序列化后接收到服务端的结果数据,在向应用程序层逆序后,将骨架部署到服务端,它的功能与托管相反,从传输层接收序列参数,在向服务端应用程序层逆序后,应用层的实现结果被序列化,最后传递给客户端。
序列组件之间的相互作用:

序列组件之间的相互作用
序列组件的概念与数据库的概念相似:

实践
序列化协议的考虑点
哪些编程语言支持和可以翻译
支持哪些平台,不论是跨平台(例如支持哪些硬件架构、操作系统)
流行度(序列涉及通信的两个方面,冷门序列协议需要高学习成本)
健壮性/鲁棒性
成熟度(协议须进行广泛、全面测试、实时系统测试、长期稳定运行)
是否简单易用
调试难度、可读性(数据序列和逆序列的准确性和业务准确性调试通常需要很长时间,良好的调试机制大大提高了开发效率.序列之后的二次序列往往不能被人眼读取.为了验证序列结果的正确性,作者必须同时写反序列程序。或者提供查询平台——这更昂贵;另一方面,如果读取器未能成功实现逆序列,很难确定它是否由反序列程序本身的错误引起,或者由编写部门编写错误的序列数据。如果数据在序列化后可读于人眼,这将大大提高调试效率,例如,XML和JSON具有人眼可读的优点。)
空间性能(Verbosity),即序列化以后的数据所占用的空间大小。
时间性能(Complexity)。复杂的序列化协议会导致较长的解析时间,这可能使得序列化和反序列化成为系统瓶颈。
扩展/兼容性:增加新领域是容易的吗? 业务系统需要快速更新,新的需要不断出现。 如果序列化协议具有良好的可扩展性,并支持自动增加新业务领域而不影响旧服务,这将提供巨大的系统灵活性。
例如,阿里的 fastjson经常有安全问题。
文档。
已知的序列化协议
早期的互联网序列化协议包括COM和CORBA。
COM主要用于Windows平台,没有实现跨平台。COM序列化利用了编译器中的虚表,使得学习成本很高。序列化得到的数据与编译器紧耦合,扩展属性非常麻烦。
CORBA更适合实现跨平台,跨语言。COBRA的主要问题是太多的参与者,导致版本过多,版本之间兼容性差,使用复杂晦涩。早期的设计成熟问题导致了COBRA的消失。J2SE 1.3的后续版本提供了基于CORBA协议的RMI-IIOP技术,CORBA可以使用纯Java开发。
目前更流行的序列协议是XML、JSON、Protobuf、Hessian、Thrift和Avro。如果你想更多地了解序列化协议,参考文献: https://en.Wikipedia.Comparison_of_data-serialization_formats
XML序列化协议
XML是一种语言,一种描述性的语言,最初的目标是编码文件,它还需要可读和可读的编码数据。XML在设计时考虑到可读性,它还有跨机器、跨语言(这里指的是人类语言)等优点。XML历史悠久,1.Version 0早在1998年就成为标准。并被广泛使用至今,所以XML已经足够成熟了。因为XML可以编码具有复杂的结构的文件,因此XML也可以用于序列对象,所以设置XML列为序列协议(例如NET框架和gSOAP框架使用XML序列。但是当XML被用作序列协议时,它就显得冗长复杂。
XML是自我描述的,XML本身是一个IDL。在XML中,有两种类型的IDL(即XML描述格式):DTD(Document Type Definition)和XSD(XML Schema Definition)。在一些编程语言中,XML有一个非常简单易用的序列API,不需要IDL文件或第三方IDL编译器(例如Java XStream)。XML在各种配置文件中广泛使用,例如O/R mapping、 Spring Bean Configuration File 等。
优点:跨平台,跨语言,成熟,可读
缺点:复杂冗余(空间复杂性)

SOAP序列化协议
SOAP(Simple Object Access protocol)是一个广泛使用的协议。基于XML的结构消息传输协议,XML用于序列和逆序列。SOAP支持多个传输协议,但最常用的是HTTP。SOAP协议IDL是WSDL(Web Service Description Language)。
如果Java应用程序层对象是:

用WSDL描述上述对象:

SOAP是安全、可扩展、多语言、多平台的,支持多种传输协议。有广泛的群众基础,基于HTTP的传输协议使得SOAP在跨越防火墙时安全。XML的人眼可读性使它具有独一无二的可调性,互联网宽带的发展逐渐弥补了其空间开支方面的巨大不足。相对较低的资料或实时数据传输要求(例如第二级);SOAP是一个很好的选择。
XML空间开销大,大的数据量和持久的应用程序场景不适合XML。XML序列和逆序列的空间和时间成本很大,对于达到MS级的性能要求的服务,不推荐XML。虽然WSDL具有描述对象的能力,但使用SOAP并不容易。对已习惯面向对象编程的用户来说,WSDL文件不是直观的。
JSON序列化协议
权威网站: http://json.com/
JSON起源于JavaScript中的”Associative array”的概念,本质就是采用”Attribute-value”方式描述对象。事实上,在JavaScript和PHP等弱型语言中,类的描述方式就是Associative array。JSON有以下优点,它很快成为最广泛使用的序列化协议之一:
1、这种Associative array格式匹配工程师对对象的理解。
2、它也有XML的人眼可读(Human-readable)优点。
3.序列化后的数据简化。
JavaScript是预定支持,在Web浏览器应用场景中被广泛使用,是Ajax的事实标准协议。
与XML相比,协议简单,分析速度快。
6、松散的Associative array使得其具有良好的可扩展性和兼容性。
因为json其实是associative array,对弱型编程语言中的概念类进行相应的处理,因此,JSON序列不需要IDL。原因:IDL的目的是写一个IDL文件,IDL文件在IDL编译器编译后生成一些代码(Stub/Skeleton)。这些代码真正负责相应的序列和反序列工作。 但是由于Associative array和一般语言里面的class太相似,他们之间存在着相应的关系。这允许我们使用一套标准代码进行相应的转换。对于自身支持Associative array的弱类型语言,语言本身具有在JSON序列之后操作数据的能力;对于Java,这种强有力的语言,可以用反射解决。
JSON可以在许多应用场景中替换XML,使分析更加简单和快速。 典型的应用场景包括:
企业间传输的数据量相对较小,而实时服务需求相对较低(例如秒)。
基于Web浏览器的Ajax请求。
由于JSON具有非常强的后继兼容性,它适用于:经常变化的接口,需要高模块化的情况,例如移动应用程序与服务端之间的通信(为什么移动应用程序使用JSON协议与服务端相互作用)。
JSON的典型应用场景是JSON+HTTP,适用于跨防火墙访问。
总体看,JSON序列额外空间成本也较大(但比XML更小),不适合大型数据量或需要持久的场景。缺乏统一的IDL减少了参与者的限制,实际操作中往往只能采用文档方式来进行约定,这可能对调试造成一些不便,延长开发周期。因为在某些语言中,JSON序列和反序列需要反射机制,因此,不建议使用需要MS级性能的系统。
Thrift序列化协议
Thrift是Facebook开发的一个RPC框架,满足了大数据量、分布式、跨语言、跨平台数据通讯的需求。Thrift内部有一个自定义的序列化协议,即Thrift序列化协议。
优点:与JSON和XML相比,Thrift提高了空间成本和分析性能,并适用于高性能系统;它支持多种编程语言,具有丰富的数据类型,并具有较强的兼容性与数据字段添加和删除。
缺点:thrift序列在thrift框架内嵌入,然而,Thrift框架不提供外部访问的Thrift序列和逆序列,文档匮乏,用起来比较困难。Thrift序列后取得的数据是二进制阵列,不具有可读性,调试相对困难。储蓄序列和框架紧耦合,无法直接读取和写入持久层的数据,不适合数据持久性场景。

Protobuf序列化协议
权威网站: https://developers.google.protocol-buffers
Protobuf具有串联协议的许多优点:
提供标准的IDL和IDL编译器, 对工程师非常友好.
序列数据是简单而紧凑的,并且序列后的数据量大约是XML的1/3到1/10。
分析速度非常快, 大约比XML快20-100倍.
它提供了一种友好的动态库,非常易于使用,并且只需要一个代码行来反演序列。
Protobuf IDL文件对每个参与者业务造成了巨大的限制
Protobuf与传输层无关,使用HTTP,具有良好的跨防火墙访问属性。
Protobuf是一个纯展示层协议,可以用于多种传输层协议;Protobuf文档也非常完善。目前仅支持Java、C++、Python三种编程语言。另外Protobuf支持的数据类型较少,不支持常量。
因此,Protobuf适用于具有高性能要求的跨公司RPC调用应用程序,而Protobuf同样适用于对象持久性。
缺点: 语言支持不足, 没有标准的传输层协议绑定, 并且在各个公司中都比较难调试.
Google gPRC框架采用了Protobuf序列协议作为参考。

希斯序列协议
Hessian(英语:Hessian)也是通用的序列协议,通常用于RPC框架,例如Dumbo和Pygeon,支持Hessian,并经常作为RPC框架的默认序列程序。
Avro序列化协议
Avro是Apache Hadoop的一个子项目,解决了JSON冗余问题,没有IDL问题.Avro提供两个序列格式:JSON和 Binary。在空间成本和分析性能方面,二进制格式与Protobuf相比较,JSON格式,方便调试.Avro支持多种数据类型,包含C++语言中的联盟类型。Avro支持JSON格式的IDL和与Thrift和Protobuf(实验阶段)类似的IDL,两者可以互换。 Schema可以同时传输数据,添加JSON自描述属性,这使得Avro非常适合动态类型语言。当Avro使文件持久时,通常与 Schema 存储,所以Avro序列文件本身具有自描述的特性,因此,它适用于Hive、Pig和MapReduce的持久数据格式。为不同版本的计划,打电话给RPC时,服务结束,客户在握手阶段可以确认对方的计划,增加数据分析速度。Avro分析性能高,数据序列简单,适用于高性能序列化服务。

序列协议基准
数据 https://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking

解析性能

序列化之空间开销
XML序列(Xstream)在性能和简单性上都差。
與Protobuf相比,Thrift在空間時間支出方面有一些缺点。
Protobuf 和 Avro 在 这 两 方面 都 非常 优越 。
序列化协议的选型
上述数种序列化协议具有各自的特点,适用于不同的场景:
1.公司间的系统调用,性能要求100ms,基于XML的SOAP协议是值得考虑的方案。
2、基于Web browser的Ajax,以及移动app与服务端之间的通讯,JSON是首选。对于性能要求不高或者以动态类型语言为主,传输数据小的场景,JSON是非常不错的选择。
JSON或XML可以在更严格的调试环境下大大提高调试效率并降低开发成本。
当场景的表演和简单度非常高时, 考虑Protobuf, Thrift, Avro.
5.Protobuf和Avro是T级数据的持久应用场景的最佳选择。 如果数据在持久后存储在Hadoop子项目中,Avro是更好的选择。
6.Avro的设计理念是面向动态类型语言的,而Avro是动态语言主要应用场景的最佳选择。
7,一个持久层非Hadoop项目,具有静态类型语言基于场景,Protobuf更符合开发习惯。
如果你需要提供一个完整的RPC解决方案, Thrift是一个很好的选择。
9、如果序列化之后需要支持不同传输协议,或需要跨防火墙访问,Protobuf可以优先考虑。
本文由 在线网速测试 整理编辑,转载请注明出处。