protobuf初识
protobuf初识
一、protobuf是什么?
protocol buffers通常称为protobuf,是Google开发的一种协议,允许对结构化数据进行序列化和反序列化。 谷歌开发它的目的是提供一种比XML更好的方式来进行系统间通信。 因此,他们专注于使其比XML更简单,更小,更快,更易于维护。该协议甚至超越了JSON,具有更好的性能,更好的可维护性和更小的尺寸。
二、序列化
1、序列化的定义
1)序列化:把对象转换为字节序列的过程称为对象的序列化。
2)反序列化:把字节序列恢复为对象的过程称为对象的反序列化。
2、为什么需要序列化和反序列化协议?
如果光看定义,是很难一下子理解序列化的意义,那么我们可以从另一个角度来推导出什么是序列化, 那么究竟序列化的目的是什么?
其实序列化最终的目的是为了对象可以跨平台存储,和进行网络传输。而我们进行跨平台存储和网络传输的方式就是IO,而我们的IO支持的数据格式就是字节数组。
因为我们单方面的只把对象转成字节数组还不行,因为没有规则的字节数组我们是没办法把对象的本来面目还原回来的,所以我们必须在把对象转成字节数组的时候就制定一种规则(序列化),那么我们从IO流里面读出数据的时候再以这种规则把对象还原回来(反序列化)。
3、序列化和反序列化基础
4、什么情况下需要序列化
1)当你想把内存中的对象状态保存到一个文件中或者数据库中时候;
2)当你想用套接字在网络上传送对象的时候。
5、如何实现序列化?
主流序列化协议:XML、JSON、Protobuf
三、Protobuf与XML、JSON的比较
1、JSON
一般的web项目中,最流行的主要还是json。因为浏览器对于json数据支持非常好,有很多内建的函数支持。json使用了键值对的方式,不仅压缩了一定的数据空间,同时也具有可读性。
1 // JSON格式 2 { 3 "firstName": "John", 4 "lastName": "Smith", 5 "age": 25, 6 "address": { 7 "streetAddress": "21 2nd Street", 8 "city": "New York", 9 "state": "NY", 10 "postalCode": "10021" 11 }, 12 "phoneNumber": [ 13 { 14 "type": "home", 15 "number": "212 555-1234" 16 }, 17 { 18 "type": "fax", 19 "number": "646 555-4567" 20 } 21 ], 22 "gender": { 23 "type": "male" 24 } 25 }
2、XML
在webservice中应用最为广泛,但是相比于json,它的数据更加冗余,因为需要成对的闭合标签。
1 // XML格式 2 <person> 3 <firstName>John</firstName> 4 <lastName>Smith</lastName> 5 <age>25</age> 6 <address> 7 <streetAddress>21 2nd Street</streetAddress> 8 <city>New York</city> 9 <state>NY</state> 10 <postalCode>10021</postalCode> 11 </address> 12 <phoneNumbers> 13 <phoneNumber> 14 <type>home</type> 15 <number>212 555-1234</number> 16 </phoneNumber> 17 <phoneNumber> 18 <type>fax</type> 19 <number>646 555-4567</number> 20 </phoneNumber> 21 </phoneNumbers> 22 <gender> 23 <type>male</type> 24 </gender> 25 </person>
3、Protobuf
Protobuf是后起之秀,是谷歌开源的一种数据格式,适合高性能,对响应速度有要求的数据传输场景。因为profobuf是二进制数据格式,需要编码和解码。数据本身不具有可读性。因此只能反序列化之后得到真正可读的数据。
适用于传输数据量大 & 网络环境不稳定的数据存储、RPC 数据交换的需求场景。如即时IM (QQ、微信)的需求场景。
// Protobuf格式 syntax = 'proto3'; package mail; message MailConfig{ string to = 1; string from = 2; string msg = 3; }
相对于其它Protobuf更具有优势
1)Protobuf的序列化的结果体积要比XML、JSON小很多,XML和JSON的描述信息太多了,导致消息要大;此外Portobuf还使用了Varint 编码,减少数据对空间的占用。
2)支持跨平台多语言
3)消息格式升级和兼容性还不错
4)Protobuf序列化和反序列化速度比XML、JSON快很多,是直接把对象和字节数组做转换,而XML和JSON还需要构建成XML或者JSON对象结构。
5)Protobuf具有比JSON更多的数据类型,如枚举和方法,并且还大量用于RPC(远程过程调用)
进一步思考:
上面的比较是是从序列化和反序列的速度以及体积的角度来进行的,但是这样的比较未免有些片断,既然Protobuf比json、xml具有优势,难道每个涉及到数据传输或者通信协议的场景,都使用Protobuf来代替其他数据格式?
为了进一步认识Protobuf以及XML、JSON之间的差别,下面我们再分两个维度进行比较, 一个是数据结构化,一个是数据序列化。这里的数据结构化主要面向开发或业务层面,数据序列化面向通信或存储层面,当然数据序列化也需要“结构”和“格式”,所以这两者之间的区别主要在于面向领域和场景不同,一般要求和侧重点也会有所不同。数据结构化侧重人类可读性甚至有时会强调语义表达能力,而数据序列化侧重效率和压缩。
从这两个维度,我们可以做出下面的一些思考。
1)数据结构化
XML
例如 XML 可以衍生出 HTML (虽然 HTML 早于 XML,但从概念上讲,HTML 只是预定义标签的 XML),HTML 的作用是标记和表达万维网中资源的结构,以便浏览器更好的展示万维网资源,同时也要尽可能保证其人类可读以便开发人员进行编辑,这就是面向业务或开发层面的数据结构化。
再如 XML 还可衍生出 RDF/RDFS,进一步表达语义网中资源的关系和语义,同样它强调数据结构化的能力和人类可读。
JSON
JSON 也是同理,在很多场合更多的是体现了数据结构化的能力,例如作为交互接口的数据结构的表达。在 MongoDB 中采用 JSON 作为查询语句,也是在发挥其数据结构化的能力
当然,JSON、XML 同样也可以直接被用来数据序列化,实际上很多时候它们也是这么被使用的,例如直接采用 JSON、XML 进行网络通信传输,此时 JSON、XML 就成了一种序列化格式,它发挥了数据序列化的能力。但是经常这么被使用,不代表这么做就是合理。实际将 JSON、XML 直接作用数据序列化通常并不是最优选择,因为它们在速度、效率、空间上并不是最优。换句话说它们更适合数据结构化而非数据序列化。
Protobuf
ProtoBuf 也具有数据结构化的能力,其实也就是上面介绍的 message 定义。我们能够在 .proto 文件中,通过 message、import、内嵌 message 等语法来实现数据结构化,但是很容易能够看出,ProtoBuf 在数据结构化方面和 XML、JSON 相差较大,人类可读性较差,不适合上面提到的 XML、JSON 的一些应用场景。
2)数据序列化
但是如果从数据序列化的角度你会发现 ProtoBuf 有着明显的优势,效率、速度、空间几乎全面占优,ProtoBuf 是极尽所能的压榨每一寸空间和性能,而其中的编码原理正是 ProtoBuf 的关键所在,message 的表达能力并不是 ProtoBuf 最关键的重点。所以可以看出 ProtoBuf 重点侧重于数据序列化而非数据结构化。
结论:
1) XML、JSON、ProtoBuf 都具有数据结构化和数据序列化的能力
2) XML、JSON 更注重数据结构化,关注人类可读性和语义表达能力。ProtoBuf 更注重数据序列化,关注效率、空间、速度,人类可读性差,语义表达能力不足(为保证极致的效率,会舍弃一部分元信息)
3)ProtoBuf 的应用场景更为明确,XML、JSON 的应用场景更为丰富。
4)在一个需要大量的数据传输的场景中,如果数据量很大,那么选择Protobuf可以明显的减少数据量,减少网络IO,从而减少网络传输所消耗的时间。
参考链接:
https://segmentfault.com/a/1190000023785960
https://www.jianshu.com/p/a24c88c0526a
https://cloud.tencent.com/developer/article/1394349