Protobuf是一种灵活高效的、用于序列化结构化数据的机制,类似于XML,但比XML更小且更简单。Protobuf序列化为二进制数据,不依赖平台和语言,同时具备很好的兼容性。
在移动应用中,客户端与服务器之间的通信协议,主流的有Facebook的Thrift、腾讯的JCE、Google的Protocol Buffer。Protobuf是Google公司内部使用的混合语言的数据标准。
Protobuf最初是在Google开发的,用来解决索引服务器的请求、响应协议。由于之前采用了一种格式用来处理请求和响应的数据的编码和解码,并支持多个版本,导致了代码丑陋且不易于维护。同时,通信协议也变得越来越复杂。因为,开发者必须确保发出请求的人和接收请求的人必须同时兼容,并且一方开始使用新协议时,另一方也可以接受。Protobuf的设计与诞生是为了解决这一类问题:
- 方便引用新字段,中间服务器可以忽略这些字段,直接传输过去而无需理解所有的字段。
- 格式可以自描述,并能在多种语言中使用。
随着Protobuf的发展它拥有了一些其他特性
- 自动生成编码和解码的代码,而无需自己编写解析器。
- 除了用于简短的RPC(Remote Procedure Call)请求外,可用来做数据存储格式。
- RPC服务器接口可作为.proto文件来描述,通过Protobuf编译器生成的存根类可供用户实现服务器接口。
在不同的计算机语言中,数据结构、对象、二进制串的表示方式并不相同。在面向对象的语言中,对象是类的实例化,例如Java中最接近数据结构的是POJO(Plain Old Java Object)或JavaBean。在半面向对象的语言如C++中,对象等同于类,数据结构等同于结构体。
对于二进制串来说,在C++中因为具有内存操作符,所以C++的字符串可以直接被传输层使用,因为它本质上就是\0
结尾的存储在内存中的二进制串。而对于Java来说,二进制串等同于字节数组。
二进制数据流
二进制数据流采用T-L-V
的数据存储方式,即”标识-长度-字段值“Tag-Length-Value
的形式表示单个数据,所有数据拼接成一个字节流,从而实现数据存储的功能。其中length
是可选存储,如存储varint
编码的数据就无需存储length
。
采用T-L-V
的存储方式的优点在于无需分隔符就能分开字段,减少了分隔符的作用。其次,各个字段存储的非常紧凑,存储空间利用率非常高。若字段没有被设置字段值,那么该字段在序列化的数据中是完全不存在的,也就不需要为它编码。相应的,字段在解码时才会被设置为默认值。
序列化与反序列化
序列化和反序列化属于通讯协议的一部分,通讯协议分层模型中,序列化和反序列化位于TCP/IP的应用层。
- 序列化是将数据结构或对象转化为二进制字符串的过程
- 反序列化是将二进制字符串转化为数据结构或对象的过程
Protobuf是一种独立于开发语言,独立于平台的可扩展的结构化数据序列机制,是一种数据交换格式的协议。Protobuf通过将结构化的数据进行序列化,从而实现数据存储和RPC数据交换的功能。
Protobuf、JSON、XML的区别
- Protobuf序列化后数据不是可读的字符串而是二进制
- XML和JSON格式的数据信息都包含在序列化后的数据中,无需任何其他信息就能还原序列化之后的数据。Protobuf需要事先定义好数据格式(.proto协议文件),还原一个序列化后的数据需要使用已定义好的数据格式。
- 在传输数据量较大的需求场景下,Protobuf比XML、JSON更小(310倍)、更快(20100倍)、使用维护更为简单。
- Protobuf可以跨平台跨语言
Protobuf的应用场景主要在传输数据量大、网络环境不稳定的数据存储、RPC数据交换的场景,如即时通讯的领域。