ProtoBuf序列化协议简介

2024-06-20 00:28

本文主要是介绍ProtoBuf序列化协议简介,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

首先,常见的序列化方法主要有以下几种:

  • TLV编码及其变体(tag, length, value): 比如ProtoBuf。
  • 文本流编码:XML/JSON
  • 固定结构编码:基本原理是,协议约定了传输字段类型和字段含义,和TLV类似,但是没有tag和length,只有value,比如TCP/IP
  • 内存dump:基本原理是,把内存中的数据直接输出,不做任何序列化操作。反序列化的时候,直接还原内存。

常见序列化方法

  1. XML可扩展标记语言(eXtensible Markup Language)。是一种通用和重量级的数据交换格式,以文本方式存储。
  2. JSON(JavaScript ObjectNotation, JS对象简谱)是一种通用和轻量级的数据交换格式,以文本结构进行存储。
  3. Protocol Buffer是Google的一种独立的轻量级的数据交换格式,以二进制结构进行存储。

序列化结果比较

XML:

在这里插入图片描述

JSON:
在这里插入图片描述

Protocol Buffer:

在这里插入图片描述

ProtoBuf使用

Protocol buffers 在序列化数据方面,它是灵活的,高效的。相比于 XML 来说,Protocol buffers 更加小巧,更加快速,更加简单。⼀旦定义了要处理的数据的数据结构之后,就可以利用 Protocol buffers 的代码生成工具生成相关的代码。甚至可以在无需重新部署程序的情况下更新数据结构。只需使用Protobuf 对数据结构进行⼀次描述,即可利用各种不同语言或从各种不同数据流中对你的结构化数据轻松读写。

Protocol buffers 很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。

ProtoBuf option部分选项
  • SPEED: 表示生成的代码运行效率高,但是由此生成的代码编译后会占用更多的空间。
  • CODE_SIZE: 和SPEED恰恰相反,代码运行效率低,但是生成的代码编译后占用更少的空间,通常用于资源有限的平台,比如Moblie。
  • LITE_RUNTIME: 生成的代码运行效率更高,同时生成的代码编译后所占用的空间也很少。这是牺牲protobuf提供的反射功能为代价。因此在C++中链接Protocol Buffer库时进需要链接libprotobuf-lite,而非libprotobuf

ProtoBuf编码

Variants编码(变长的类型使用)

为什么设计变长编码:普通的 int 数据类型, 无论其值的大小, 所占用的存储空间都是相等的,比如不管是0x12345678 还是0x12都占用4字节,那能否让0x12在表示的时候只占用1个字节呢?

是否可以根据数值的大小来动态地占用存储空间, 使得值比较小的数字占用较少的字节数, 值相对比较大的数字占用较多的字节数, 这即是变长整型编码的基本思想。

采用变长整型编码的数字, 其占用的字节数不是完全⼀致的, Varints 编码使用每个字节的最高有效位作为标志位, 而剩余的 7 位以⼆进制补码的形式来存储数字值本身, 当最高有效位为 1 时, 代表其后还跟有字节, 当最高有效位为 0 时, 代表已经是该数字的最后的⼀个字节。

在 Protobuf 中, 使用的是 Base128 Varints 编码, 在这种方式中, 使用 7 bit (即2的7次方为128)来存储数字, 在 Protobuf 中, Base128 Varints 采用的是小端序, 即数字的低位存放在高地址, 举例来看, 对于数字 1, 我们假设 int 类型占 4 个字节, 以标准的整型存储, 其⼆进制表示应为

00000000 00000000 00000000 00000001

可见,只有最后一个字节存储了有效数值,前三个字节都为0,若采用Variants编码,其二进制形式为

00000001

因为其没有后续字节,因此最高有效位为0,其余的7位以补码形式存放1,再比如数字666:在这里插入图片描述

Zigzag编码(针对负数)

Varints 编码的实质在于去掉数字开头的 0, 因此可缩短数字所占的存储字节数, 在上面的例子中, 只举例说明了正数的 Varints 编码, 但如果数字为负数, 则采用 Varints 编码会恒定占用 10 个字节, 原因在于负数的符号位为 1, 对于负数其从符号位开始的高位均为 1, 在 Protobuf 的具体实现中, 会将此视为⼀个很大的无符号数。

Varints 编码的实质在于设法移除数字开头的 0 比特, 而对于负数, 由于其数字高位都是 1, 因此 Varints 编码在此场景下失效

Zigzag 编码便是为了解决这个问题, Zigzag 编码的大致思想是首先对负数做⼀次变换, 将其映射为⼀个正数, 变换以后便可以使用Varints 编码进行压缩, 这里关键的⼀点在于变换的算法, 首先算法必须是可逆的, 即可以根据变换后 的值计算出原始值 , 否则就无法解码, 同时要求变换算法要尽可能简单, 以避免影响Protobuf编码、解码的速度。解码方式为:

在这里插入图片描述

数据组织

Protobuf 不是完全自描述的信息描述格式, 接收端需要有相应的解码器(即 proto 定义)才可解析数据格式, 序列化后的 Protobuf 数据不携带字段名, 只使用字段编号来标识⼀个字段, 因此更改 proto 的字段名不会影响数据解析(但这显然不是⼀种好的行为), 字段编号会被编码进⼆进制的消息结构中, 因此我们应尽可能地使用小字段编号。

同时,Protobuf 是⼀种紧密的消息结构, 编码后字段之间没有间隔, 每个字段头由两部分组成: 字段编号和 wire type, 字段头可确定数据段的长度, 因此其字段之前无需加入间隔, 也无需引入特定的数据来标记字段末尾, 因此 Protobuf 的编码长度短, 传输效率高。

最后给大家推荐一个LinuxC/C++高级架构系统教程的学习资源与课程,可以帮助你有方向、更细致地学习C/C++后端开发,具体内容请见 https://xxetb.xetslk.com/s/1o04uB

这篇关于ProtoBuf序列化协议简介的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1076581

相关文章

Java Stream 并行流简介、使用与注意事项小结

《JavaStream并行流简介、使用与注意事项小结》Java8并行流基于StreamAPI,利用多核CPU提升计算密集型任务效率,但需注意线程安全、顺序不确定及线程池管理,可通过自定义线程池与C... 目录1. 并行流简介​特点:​2. 并行流的简单使用​示例:并行流的基本使用​3. 配合自定义线程池​示

PostgreSQL简介及实战应用

《PostgreSQL简介及实战应用》PostgreSQL是一种功能强大的开源关系型数据库管理系统,以其稳定性、高性能、扩展性和复杂查询能力在众多项目中得到广泛应用,本文将从基础概念讲起,逐步深入到高... 目录前言1. PostgreSQL基础1.1 PostgreSQL简介1.2 基础语法1.3 数据库

Java整合Protocol Buffers实现高效数据序列化实践

《Java整合ProtocolBuffers实现高效数据序列化实践》ProtocolBuffers是Google开发的一种语言中立、平台中立、可扩展的结构化数据序列化机制,类似于XML但更小、更快... 目录一、Protocol Buffers简介1.1 什么是Protocol Buffers1.2 Pro

Python库 Django 的简介、安装、用法入门教程

《Python库Django的简介、安装、用法入门教程》Django是Python最流行的Web框架之一,它帮助开发者快速、高效地构建功能强大的Web应用程序,接下来我们将从简介、安装到用法详解,... 目录一、Django 简介 二、Django 的安装教程 1. 创建虚拟环境2. 安装Django三、创

Java对接MQTT协议的完整实现示例代码

《Java对接MQTT协议的完整实现示例代码》MQTT是一个基于客户端-服务器的消息发布/订阅传输协议,MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛,:本文主要介绍Ja... 目录前言前置依赖1. MQTT配置类代码解析1.1 MQTT客户端工厂1.2 MQTT消息订阅适配器1.

Linux中的自定义协议+序列反序列化用法

《Linux中的自定义协议+序列反序列化用法》文章探讨网络程序在应用层的实现,涉及TCP协议的数据传输机制、结构化数据的序列化与反序列化方法,以及通过JSON和自定义协议构建网络计算器的思路,强调分层... 目录一,再次理解协议二,序列化和反序列化三,实现网络计算器3.1 日志文件3.2Socket.hpp

Linux中的HTTPS协议原理分析

《Linux中的HTTPS协议原理分析》文章解释了HTTPS的必要性:HTTP明文传输易被篡改和劫持,HTTPS通过非对称加密协商对称密钥、CA证书认证和混合加密机制,有效防范中间人攻击,保障通信安全... 目录一、什么是加密和解密?二、为什么需要加密?三、常见的加密方式3.1 对称加密3.2非对称加密四、

MySQL 索引简介及常见的索引类型有哪些

《MySQL索引简介及常见的索引类型有哪些》MySQL索引是加速数据检索的特殊结构,用于存储列值与位置信息,常见的索引类型包括:主键索引、唯一索引、普通索引、复合索引、全文索引和空间索引等,本文介绍... 目录什么是 mysql 的索引?常见的索引类型有哪些?总结性回答详细解释1. MySQL 索引的概念2

Olingo分析和实践之EDM 辅助序列化器详解(最佳实践)

《Olingo分析和实践之EDM辅助序列化器详解(最佳实践)》EDM辅助序列化器是ApacheOlingoOData框架中无需完整EDM模型的智能序列化工具,通过运行时类型推断实现灵活数据转换,适用... 目录概念与定义什么是 EDM 辅助序列化器?核心概念设计目标核心特点1. EDM 信息可选2. 智能类

SpringSecurity整合redission序列化问题小结(最新整理)

《SpringSecurity整合redission序列化问题小结(最新整理)》文章详解SpringSecurity整合Redisson时的序列化问题,指出需排除官方Jackson依赖,通过自定义反序... 目录1. 前言2. Redission配置2.1 RedissonProperties2.2 Red