认识protobuf
由于时间原因,成功由周更变成了月更,最近加深了自己对架构的理解,之后的文章,可能会不限于语言而更多的是记录一下自己对抽象和架构的思考。
起因:在重构一个小模块的时候发现后端之前的脚手架中用了protobuf这种序列化通信协议取代了传统的json数据格式,便仔细研究了下,直接打开新世界的大门。
什么是protobuf
protobuf是Google开源的一款支持跨平台、语言中立的结构化数据描述和高性能序列化协议,此协议完全基于二进制,所以性能要远远高于JSON/XML。由于出色的传输性能所以常见于微服务之间的通讯,其中最为著名的是Google开源的 gRPC 框架。
Protobuf对于不同的字段类型采用不同的编码方式和数据存储方式对消息字段进行序列化,以确保得到高效紧凑的数据压缩。
protobuf如何序列化
1
判断每个字段是否有设置值,有值才进行编码。
2
根据字段标识号与数据类型将字段值通过不同的编码方式进行编码。
3
将编码后的数据块按照字段类型采用不同的数据存储方式封装成二进制数据流
如何反序列化
1
调用消息类的parseFrom(input)解析从输入流读入的二进制字节数据流。
2
将解析出来的数据按照指定的格式读取到Java、C 、Phyton对应的结构类型中。
和json比较
通过这些定义,我们基本可以推断出它的好处,他的速度比json要快,数据流也更小。使用protobuf表示的数据能更加高效,并且将数据压缩得更小,大约是json格式的1/10,xml格式的1/20。那么同样带宽情况下,传输效率就会更高。
protobuf协议原理
基于128bits的数据存储方式(Base 128 Varints)
Varint 是一种紧凑的表示数字的方法。它用一个或多个字节来表示一个数字,值越小的数字使用越少的字节数。这能减少用来表示数字的字节数。
这里有一篇很详细的文章分享给大家:https://blog.haohtml.com/archives/20215
我这里就不过多赘述了。
如何使用proto到项目中
protobuf的数据还支持从proto文件生成不同编程语言文件的机制。也就是说你根据protobuf的官方文档写出一个你想要的proto数据定义文件,然后用protoc文件,就可以生成一个类文件,然后引用就可以用了。
看下面的例子(以python为例):
根据这个proto文件生成python类
1.执行命令protoc printer.proto --python_out=. -I.
就会发现在目录下生成了python的类文件
2. 在其他文件引用
随后就可以用python中的proto的库对这个对象进行任何操作了。
protobuf的优点
1
1、性能好/效率高
protobuf在序列化和反序列化进行了优化。可以使序列化和反序列化的时间开销都减短。
空间开销:也减少了很多
2、有代码生成机制,如上面的例子。
3、支持向后兼容和向前兼容
4、支持多种编程语言
在Google官方发布的源代码中包含了c 、java、Python三种语言
一些缺点
2
1、二进制格式导致可读性差
为了提高性能,protobuf采用了二进制格式进行编码。这直接导致了可读性差。这个直接影响开发测试时候的效率。当然,一般情况下,protobuf非常可靠,并不会出现太大的问题。
2、缺乏自描述
一般来说,XML是自描述的,而protobuf格式则不是。给你一段二进制格式的协议内容,不配合你写的结构体是看不出来什么作用的。
3、通用性差
protobuf虽然支持了大量语言的序列化和反序列化,但仍然并不是一个跨平台和语言的传输标准。在多平台消息传递中,对其他项目的兼容性并不是很好,需要做相应的适配改造工作。相比json 和 XML,通用性还是没那么好。
从数据角度看
3
最后,说说除了一些技术层面的考虑之外,我自己从另外一个角度对protobuf的看法。
自从加深了对架构和抽象的了解。我认为json这种通用的数据格式协议用在restful接口协议规范里十分和谐,但是restful规范在我看来,它的通用性和抽象层级并没有达到我们的要求,特别是当我们要把sass服务扩展到pass服务的时候,。
当我们在设计一个更加抽象的层级关系的时候,就要拥有面对数据的思维,这点我是很喜欢protobuf的,因为它可以让我很直观的抽象数据结构的设计。
公众号|请关注
我和bug只能活一个