考虑以下的场景
- 编码中需要将一个对象存储在文件中,需要时再拿出来
- 缓存一个对象,等需要的时候取出来。比如服务器接收到一个订单,这个订单只要等客户确认之后才能继续往下处理,订单被抽象成一个Order数据类型的对象。我们需要先把它写到缓存中。
- 给某服务发送一大包json数据,我们要把数据变成文本或字节
序列化和反序列化
对于场景一,似乎我们只要把对象转换成文本字节的格式放在一个磁盘文件里就可以,给它命名,然后保存起来。这个过程粗略可以视为是序列化,然而问题没有那么简单,对于简单的对象,这是可以的。
例如
typedef struct {
string name;
int age;
} Person;
Person p = Person("donghua", 18);
我们可以先将对象转换成一个字典,然后保存它的类型名称,拼接成一串文本的格式
"Person;{\"name\":\"donghua\",\"age\":18}"
转成伪代码:
void serialze(const Person& p) {
classname = getClassName(p); //反射得到类名
json = toJson(p); // 将数据按key-value的值转成json
writeRoDisk(classname, json); //组成文本字节格式放到磁盘中
}
在网络传输的应用中,序列化起码需要满足几个要求:
- 序列化之后,字节大小尽量少
- 对端收到之后,知道怎么还原出来
- 序列化的过程和反序列化的过程不要太损耗cpu
- 跨语言传输。例如Java服务通过序列化和反序列化能够实现和Python服务沟通
- 跨端,能够满足windows服务器和Linux服务器
序列化和反序列化的实现广泛见于各种RPC框架,为了满足以上各种需求,普遍地,序列化和反序列化框架都采用 IDL 来标准化协议。IDL是 接口描述语言(Interface description language)
example:
syntax = "proto2";
package tutorial;
option java_package = "com.example.tutorial";
option java_outer_classname = "AddressBookProtos";
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phones = 4;
}
message AddressBook {
repeated Person people = 1;
}
使用protobuf提供的编译器,可以将接口描述语言翻译成高级编程语言。IDL独立于高级编程语言,它的设计是为了实现编程语言之间的沟通,因此它有一定的规范性和共同遵守的约定。
注意,编译未必是高级编程语言翻译成二进制,它可以是其它形式的转换
序列化和反序列化的用途:
- 网络通信传输。
- 数据存储。
- RPC(远程过程调用), 如SOAP, thrift。
- 在以组件为基础,例如在COM中用于进程间通信,动态对象创建;的软件工程中,是对象的分布式方法。
- 检测随时间数据变动的方法。
常见的接口描述语言(IDL)
IDL名称 | 英文全称 | 主要的应用场景 | 简介 | 优点 |
---|---|---|---|---|
COM | Component Object Model 组件对象模型 |
进程间通信 | 微软开发的一组软件组件之间二进制接口标准 主要应用于进程间通信,动态对象创建 可以将COM看成是一组软件组件之间对象交互的规范 |
跨语言,windows平台 |
COBRA | Common Object Request Broker Architecture | 对象分布式 | 编程语言无关 操作系统无关 底层通讯机制相当灵活 |
支持C/C++,smalltalk,perl,Java and C++, C-only, SmallTalk, Perl, Ada, Ruby, and Python 等语言都有CORBA的实现,并且可以跨语言互操作 |
XML-RPC | Web服务通信 | 一种分布式计算协议,是SOAP的前身 | 跨语言 | |
JSON | JavaScript Object Notation | Web服务数据通信 | 道格拉斯·克罗克福特(构想和设计的一种轻量级数据交换格式 JSON的格式描述可以参考RFC 4627 |
跨语言 |
Trift | rpc 调用 | Facebook开发的rpc调用框架,类似protobuf ,它本身是一个框架,内置了一种接口描述语言和二进制通讯协议 | ||
Protobuf | rpc调用 | 广泛使用的rpc序列化数据结构协议 | 略 | 高性能 |
SOAP | Simple Object Access Protocol 简单对象访问协议 |
Web服务中数据交换 | SOAP为了简化网页服务器(Web Server)从XML 数据库中提取数据时,节省去格式化页面时间,以及不同应用程序之间按照HTTP通信协议,遵从XML格式执行资料互换,使其抽象于语言实现、平台和硬件。此标准由IBM、微软、UserLand和DevelopMentor 在1998年共同提出,并得到IBM、莲花(Lotus)、康柏(Compaq)等公司的支持,目前SOAP 1.1版是业界共同的标准,属于第二代的XML协议(第一代具主要代表性的技术为XML-RPC以及WDDX)。 | |
Avro | Json的加强版 | rpc | 主要用于Hadoop |
Python中的序列化
以上大概罗列了一些针对序列化典型问题出现的序列化工具,大多数是包含了接口描述协议,在python语言中,如果只是应用于数据存储这种简单的场景,有标准的pickle模块以及marshal,通常我们使用pickle,marshal比较古老
参考资料:
SOAP简史
Thrift 的缘起和理论基础
Python序列化