在IM中使用Protobuf通信

676 阅读6分钟

序言

本文共 1947字,预计阅读需要 5 分钟

通读本文你可以了解到以下几个信息

  1. Protobuf是什么,适用什么场景
  2. 为什么同样的数据Protobuf比其它常用的数据格式要小很多
  3. Protobuf怎么安装使用

一、前言

protobuf是google提供的一个开源序列化框架

在日常的IM通信中,用户和客服之间在不断的进行着实时的信息交换,随着业务的不断扩展用户量的不断提升,进线咨询的数量也在不断攀升,尤其是在大促期间高并发量场景激增,对于同时接线多个用户的客服和支撑消息交换传输的服务器来说是一个不小的挑战

这个时候会对信息的接收和发送速度要求越来越高,要提高数据的传输效率,就必然需要考虑传输过程中的数据体积大小和占用带宽了

二、IM通信中常用的数据格式,以及他们之间的区别

  1. 在IM通信中常用的数据格式JSON(目前客服IM使用的方式),XML,Protobuf等

JSON:

是一种轻量级的数据交换格式,它以文本的形式表示数据对象,易于阅读和编写,同时也便于机器解析和生成。JSON在Web和手机应用程序的开发中广泛应用,是当前最流行的数据格式之一。序列化、反序列化容易,调试方便,可视化强,但是相对于二进制存储占用的体积较大

XML:

因为占用空间大解析速度慢没有过多去了解

Protobuf :

是一种轻便高效的结构化数据序列化和反序列化协议,可以将结构化数据进行编码,并将其序列化为二进制格式,可用于数据存储、通信协议、配置文件等场景。在IM通信中,使用Protobuf可以提高数据传输效率,缩短消息传输时间。序列列化后的大小是json的10分之一,xml格式的20分之一

功能XMLJSONProtobuf
格式纯文本格式纯文本格式二进制格式
可读性易于阅读和编写易于阅读和编写不易阅读
性能解析速度较慢解析速度较慢解析速度快
数据量数据占用的空间较大数据占用的空间较大数据占用的空间较小
实现难度实现难度较高实现难度较低实现难度较高
扩展性扩展性较好扩展性较差扩展性较好
语言支持广泛支持广泛支持比较少

从上面的对比来看,Protobuf序列化后的体积更小,传输效率更高,耗时更少等优点,虽然实现难度较高,谷歌提供开源的库支持数据的序列化和反序列化。在开发的前期为了能直观的查看数据和方便调试选型使用的是纯文本易于阅读和编写的JSON数据格式,随着业务的发展壮大,后续使用Protobuf作为IM通信数据传输格式会是一个不错的选择

  1. 官网这么介绍

Protocol Buffers are a language-neutral, platform-neutral extensible mechanism for serializing structured data.

与语言无关,与平台无关,可扩展并且可以向后兼容,根据已有数据的结构可以进行升级

  1. 应用实例

  • 因为Protobuf是 Google 开发开源的,Google 大量服务都在使用 Protobuf 进行通信
  • Facebook、Twitter、Uber、Dropbox 等知名公司,以及一些开源项目都是基于 Protobuf 进行数据传输

三、Protobuf如何缩小消息大小的

  1. 编码格式:Protobuf 所采用的二进制编码格式更加紧凑,采用字节流进行传输,不依赖于字符编码,这样在传输数据时能够更快、更省带宽
  2. 特定数据类型:Protobuf 提供了很多特定数据类型,用于表示常见的数据类型,例如 int、float、bool、double、枚举等,这些类型所占用的字节数较少,可以减小消息体积
  3. 动态长度编码:Protobuf 采用了一种变长编码方式,即 varint 编码,用于压缩常见数值类型,将数值编码成一个可变长度的字节数组,从而能够表示范围更大的整数,减少了消息体积的消耗。
  4. 消息格式:例如,在 JSON 中需要使用键-值对来表示字段名和字段值,每个键-值对都需要包含双引号、冒号和逗号等符号,这会占用不少的消息体积。而 Protobuf 的编码格式方法相对紧凑,用标识符和字节数组来表示字段和它们的值,没有额外的符号开销
  5. 使用枚举类型:在 .proto 文件中使用枚举类型代替字符串类型,因为如果使用字符串类型,每个字符串都需要用一个字节数组表示,而使用枚举类型只需要一个整数即可,可以减小消息大小
  6. 使用嵌套结构:在 .proto 文件中使用嵌套结构代替扁平结构可以减少对重复字段进行编码的次数,从而减小消息大小。

综上所述,主要有编码格式、特定数据类型、动态长度编码和消息格式等多方面的因素。这使得 Protobuf 能够在网络传输时更加高效,快速和节省带宽。

四、消息的序列化和反序列化

  1. 序列化:将消息转化为二进制格式,以便传递或持久化数据
  2. 反序列化:将二进制格式的消息转化为原始消息格式

可以通过纯原生的JavaScript实现,声明需要使用的消息类型并执行序列化和反序列化就可以了

除了原生实现方式以外也可以通过第三方库,比如 protobuf.js、pbf、protobuf-lite 等

五、实践:安装和使用

  1. 如何安装

//安装命令

brew install protobuf



//检查安装是否成功

protoc --version 

  1. 示例

安装好环境之后我们来看一个简单的示例

先定义一个.proto文件,然后将 .proto 文件编译生成JavaScript代码文件,编译后生成的代码文件可以引入到前端代码中使用

protoc --js_out=import_style=commonjs,binary:. src/demo.proto



--js_out 参数指定了输出格式和路径

import_style=commonjs 表示生成 CommonJS 风格的代码

binary 表示采用二进制格式编码数据

六、结语

  1. 数据传输格式各有利弊,根据现有的业务场景选择更适合传输格式是一个不错的方式,希望本篇文章对未来的客服技术更新迭代带来些许助力
  2. 本篇文章只是对Protobuf的一些介绍和简单的使用示例后续再继续补充扩展Protobuf进行通信时的具体交互细节内容

比如使用Protobuf进行通信时

  • 如何在前端中发送消息

  • 如何在前端中接收并解析消息

  • 如何在前端中和后端之间使用Protobuf进行通信

官方文档地址:protobuf.dev/programming…