ProtoBuf协议到底是什么?
工作中所使用的传输协议,下面就来一探究竟,为何众多协议选择了它?
前言
在移动互联网时代,手机流量、电量是最为有限的资源,而移动端的即时通讯应用无疑必须得直面这两点。
解决流量过大的基本方法就是使用高度压缩的通信协议,而数据压缩后流量减小带来的自然结果也就是省电:因为大数据量的传输必然需要更久的网络操作、数据序列化及反序列化操作,这些都是电量消耗过快的根源
当前即时通讯应用中最热门的通信协议无疑就是Google的Protobuf了,基于它的优秀表现,微信和手机QQ这样的主流IM应用也早已在使用它。本文将详细介绍Protobuf的使用、原理等。
这个协议主要是干什么用的?
主要是在即时通讯中将定义好的数据结构按照格式序列化传输
同样功能的协议有哪些? 区分?
XMPP、Protobuf、JSON、私有2进制、MQTT、定格化XML、Plain text等等; 对于各种协议的每一种特点在了解后,积累了经验后就有了对于协议传输的选型经验了,每种都有适合的场景。
1. 自定义二进制
优点:信息体积小,对应以上”1“
缺点:编码复杂度高(自己定义消息格式,自己编写序列化和反序列化方法,自己进行容错处理,可扩展性不强,比如添加个字段,就必须改两端的逻辑处理),对应以上”3“;
2. 提供序列化和反序列化库的开源协议
比如 谷歌的protocol buffers, json, Thrift
优点:是一种流行的通用数据格式,扩展相当方便,序列化和反序列化相当方便(有相应库),错误处理方便(库支持)
3. 文本化协议
比如xml,json
优点:序列化,反序列化容易(库支持),调试方便,可视化强;
缺点:相对于二进制存储占用体积大。
1. 数据格式选择需要考虑的方面
网络数据大小:占用带宽,传输效率
虽然对单个用户来说,数据量传输很小,但是对于服务器端要承受众多的高并发数据传输(尤其现时高并发、大用户量的IM聊天应用和实时推送服务端等场景),必须要考虑到数据占用带宽,尽量不要有冗余数据,这样才能够少占用带宽,少占用资源,少网络IO,提高传输效率。
2. 网络数据安全性:敏感数据的网络安全
对于相关业务的部分数据传输都是敏感数据,所以必须考虑对部分传输数据进行加密。这通常出现在银行等数据安全性要求很高的应用行业和场景里,当然传统的即时通讯应用里基于用户隐私考虑,数据加密也是同样是个必须考虑的问题。安全性是应用的基础条件,需求是一样的,只是加密程度、安全性级别要求有不同而已。
3. 编码复杂度
码复杂度包括序列化和反序列化复杂度、效率、数据结构的可扩展性和可维护性。越简单越实用的将越流行,便于开发维护和可扩展。
4. 协议通用性、大众规范
大家好才是真的好,独立分子走不久远。众多平台千万家,你不融入换下家。
1. Protobuf简介
一条消息数据,用protobuf序列化后的大小是json的10分之一,xml格式的20分之一,是二进制序列化的10分之一,总体看来ProtoBuf的优势还是很明显的。
ProtoBuf的优势 (灵活高效,比xml快,易于使用,语法定义结构化,语言支持众多)
Protobuf 有如 XML,不过它更小、更快、也更简单。你可以定义自己的数据结构,然后使用代码生成器生成的代码来读写这个数据结构。你甚至可以在无需重新部署程序的情况下更新数据结构。只需使用 Protobuf 对数据结构进行一次描述,即可利用各种不同语言或从各种不同数据流中对你的结构化数据轻松读写。
它有一个非常棒的特性,即“向后”兼容性好,人们不必破坏已部署的、依靠“老”数据格式的程序就可以对数据结构进行升级。这样您的程序就可以不必担心因为消息结构的改变而造成的大规模的代码重构或者迁移的问题。因为添加新的消息中的 field 并不会引起已经发布的程序的任何改变。
Protobuf 语义更清晰,无需类似 XML 解析器的东西(因为 Protobuf 编译器会将 .proto 文件编译生成对应的数据访问类以对 Protobuf 数据进行序列化、反序列化操作)。
使用 Protobuf 无需学习复杂的文档对象模型,Protobuf 的编程模式比较友好,简单易学,同时它拥有良好的文档和示例,对于喜欢简单事物的人们而言,Protobuf 比其他的技术更加有吸引力。
2. 适用场景
- 需要和其它系统做消息交换的,对消息大小很敏感的。那么protobuf适合了,它语言无关,消息空间相对xml和json等节省很多。比如游戏场景中大量数据会产生交互,就会节省许多消耗。
- 小数据的场合。如果你是大数据,用它并不适合。
- 项目语言是c++,java,python的,因为它们可以使用google的源生类库,序列化和反序列化的效率非常高。其它的语言需要第三方或者自己写,序列化和反序列化的效率不保证。 谷歌大大手写的优化他不香吗!
3. 如何使用,揭开面纱
一个helloworld.proto文件 将我们需要传输的字段以下列方式message的形式进行传输
package lm;
message helloworld
{
required int32 id = 1; // ID
required string str = 2; // str
optional int32 opt = 3; //optional field
}
然后我们再程序中进行解码解析读取,加密传输都按照proto相关的语言利用api进行传输,这里可以自行百度具体语言对于proto的操控传输