Protobuf:一种更小、更快、更高效的协议

article/2025/8/30 8:08:19

C/C++Linux服务器开发/后台架构师知识体系

Protobuf介绍

Protobuf (Protocol Buffers) 是谷歌开发的一款无关平台,无关语言,可扩展,轻量级高效的序列化结构的数据格式,用于将自定义数据结构序列化成字节流,和将字节流反序列化为数据结构。所以很适合做数据存储和为不同语言,不同应用之间互相通信的数据交换格式,只要实现相同的协议格式,即后缀为proto文件被编译成不同的语言版本,加入各自的项目中,这样不同的语言可以解析其它语言通过Protobuf序列化的数据。目前官方提供c++,java,go等语言支持。

下面表格是支持语言的列表及各个语言的插件

支持语言很多,C++ java python php golang 等,支持列表

语言github插件地址
C++ (include C++ runtime and protoc)src https://github.com/protocolbuffers/protobuf/tree/master/src
Javajava https://github.com/protocolbuffers/protobuf/tree/master/java
Pythonpython https://github.com/protocolbuffers/protobuf/tree/master/python
Objective-Cobjectivec https://github.com/protocolbuffers/protobuf/tree/master/objectivec
C#csharp https://github.com/protocolbuffers/protobuf/tree/master/csharp
JavaScriptjs https://github.com/protocolbuffers/protobuf/tree/master/js
PHPallegro/php-protobuf https://github.com/allegro/php-protobuf
Goruby https://github.com/protocolbuffers/protobuf/tree/master/ruby
PHPgolang/protobuf https://github.com/golang/protobuf

Protobuf应用场景

对于protobuf的使用场景,简单来说,业务要求命中其优点越多,缺点越少,就更能够使用Protobuf,比如说在某些场景对消息大小很敏感,或者传输的数据量不大,比如说APP登录场景,那么可以考虑使用Protobuf

选择序列化协议需要考虑哪些

序列化之后的数据流的大小(占用网络带宽),对于高并发的场景下这点很重要。
序列化和反序列化的性能(占用CPU和内存资源)。
是否支持多语言。

常见数据交互格式对比

  • JSON (JavaScript Object Notation):一般用于WEB项目中,因为浏览器对JSON格式的数据支持非常好,大部分编程语言有很多内建函数支持,而且JSON几乎支持所有编程语言。
  • XML:XML在WebService中的应用比较多,相比于JSON,它的数据更加冗余,因为需要成对的闭合标签,而JSON使用了键值对的方式,不仅压缩了一定的数据空间,同时也有更好的可读性。
  • Protobuf:谷歌公司新开发的一种数据格式,适合高性能,对响应速度有要求的数据传输场景。因为Protobuf是二进制数据格式,需要编码和解码。数据本身不具有可读性,因此只能反序列化得到可读数据。

相对于其他数据格式Protobuf的优势:

  • 序列化后体积比JSON和XML小,适合网络传输。
  • 序列化反序列化速度快,比JSON的处理速度快。
  • 消息格式升级和兼容性还不错。

Protobuf的序列化与反序列化.

  • 序列化:将数据结构或者对象转化成二进制串的过程。
  • 反序列化:将序列化过程中所产生的二进制串转换成数据结构或对象的过程。

Protobuf的优点和缺点

优点:

  • Protobuf序列化速度快,序列化后的体积比xml更小,传输更快。使用相对也简单,因为Proto编译器能自己序列化和反序列化。
  • 可以定义自己的数据结构,然后使用代码生成器去生成的代码来读写这个数据结构,甚至可以在不用重新部署的情况下来更新这个数据结构,只需要使用Protobuf对数据结构进行一次描述,就可以利用不同的语言或者从不同的数据流对你的结构化数据轻松的读写。
  • 向后兼容性好,不需要破坏旧的数据格式,依靠老的数据格式的程序就可以对数据结构更新。
  • 语义比xml更加清晰,无需类似xml解析器的东西(因为Protobuf编译器会将.proto文件编译成对应的数据访问用以对Protobuf数据进行序列化和反序列化操作)。
    跨平台,跨语言,可扩展性好。
  • 维护成本比较低,多个平台只需要维护一套.proto对象协议文件。
    加密性好。

缺点:

  • Protobuf功能简单,无法用来表示复杂的概念。
  • 相比xml,xml具有某种程度的自解释性,因为最终是转成二进制流,不像xml和json能够直接查看明文。

那么为什么不直接使用XML

同XML相比,Protobuf的优势在于高性能,它以高效的二进制存储方式比XML小3到10倍,快20到100倍,原因在于:

  • ProtoBuf序列化后所生成的二进制消息非常紧凑。
  • ProtoBuf封解包过程非常简单。

protobuf对传输的数据采取一种最简单的key-value形式的存储方式(但其中有一种类型的数据不是k-v形式,后面会讲),这钟存储方式极大的节省了空间。除此之外protobuf还采取了varint(变长编码)形式来压缩数据,对体积较小的字段分配较少的空间,由此使得压缩后的文件非常“紧凑”。

Protobuf语法

要想使用Protobuf就需要先定义proto文件,先熟悉protobuf消息定义的相关语法。

1. 定义消息类型

syntax = "proto3";message SendRequest {string query = 1;int32 page_number = 2;repeated int32 result_per_page = 3;
}

.proto文件的第一行指定了使用proto3语法,说明使用的是proto3版本。如果省略protocol buffer编译器就默认使用proto2语法。他必须是文件中非空非注释行的第一行。

message表示消息类型,可以有多个。

SendRequest定义中指定了三个字段(name/value键值对),每个字段都会有名称和类型。

repeated是字段规则。

Protobuf各个语言标量类型对应关系

一个标量消息字段可以含有一个如下类型,下面表格定义了在.proto文件中的类型,以及与之对应在自动生成访问类中定义类型。
在这里插入图片描述

2. 定义字段的规则

message的字段必须符合以下规则:

singular:一个遵循singular规则的字段,在一个结构良好的message消息体(编码后的message)可以有0或1个该字段(但是不可以有多个)。这是proto3语法的默认字段规则。(这个理解起来有些晦涩,举例来说上面例子中三个字段都是singular类型的字段,在编码后的消息体中可以有0或者1个query字段,但不会有多个。)

repeated:遵循repeated规则的字段在消息体重可以有任意多个该字段值,这些值的顺序在消息体重可以保持(就是数组类型的字段)

3. 添加更多消息类型

在单个.proto文件中可以定义多个message,这在定义多个相关message时非常有用。比如说,我们定义SendRequest对应的响应messageSendResponse,把它加到之前的.proto文件中。

syntax = "proto3";message SendRequest {string query = 1;int32 page_number = 2;repeated int32 result_per_page = 3;
}message SendResponse {...
}

4. 添加注释

.proto文件中的注释和C,C++的注释风格相同,使用// 和 /* … */

syntax = "proto3";message SendRequest {string query = 1;         // 查询int32 page_number = 2;    // 页码repeated int32 result_per_page = 3;   //分页数
}

5. message支持嵌套使用

message SendResponse {message Result {string url = 1;string title = 2;repeated string snippets = 3;}repeated Result results = 1;
}

6.使用其它消息类型

可以将其它消息类型作为字段的类型,如下,有多个message中都包含Person类型,此时就可以在相同的.proto文件定义一个Person类型,然后在需要用到的message中指定一个Person字段。

message Personinfo {repeated Person info = 1;
}
message Person {string name = 1;int32 age = 2;repeated int32 weight = 3;
}

上面也可以嵌套在一起写

message Personinfo {message Person {string name = 1;int32 age = 2;repeated int32 weight = 3;}repeated Person info = 1;
}

如果想在它的父消息类型外部重用这个消息类型,可以使用Personinfo.Person的方式

message PersonMessage {Personinfo.Person info = 1
}

7. 定义服务(Service)

如果想将消息类型用在RPC系统中,可以在.proto文件中定义一个RPC服务接口,protobuf编译器会根据所选择语言生成对应语言的服务接口代码及存根。例如定义一个RPC服务并具有一个方法,该方法能够接受SearchRequest并返回一个SearchResponse,此时就可以在.proto文件进行如下定义:

service SearchService {//rpc(rpc关键字) 服务函数名  (传入参数) 返回(返回参数)rpc  Search (SearchRequest) returns (SearchResponse) ;
}

gRPC就是使用Protobuf的一个RPC系统,gRPC在使用Protobuf时候非常有效。

Protobuf是如何工作的

.proto文件是protobuf一个重要的文件,它定义了需要序列化数据的结构,当protobuf编译器(protoc)来运行.proto文件时候,编译器将生成所选择的语言的代码,比如你选择go语言,那么就会将.proto转换成对应的go语言代码,对于go来说,编译器会为每个消息类型生成一个pd.go文件,而C++会生成一个.h文件和一个.cc文件。

使用protobuf的3个步骤是:

  • 在.proto文件中定义消息格式。
  • 用protobuf编译器编译.proto文件。
  • 用C++/Java/go等对应的protobuf API来写或者读消息。

在.proto文件定义消息,message是.proto文件最小的逻辑单元,由一系列name-value键值对构成。下面的.proto文件定义了一个"人"的消息:

message Person {required string name = 1;required int32 id = 2;optional string email = 3;enum PhoneType {MOBILE = 0;HOME = 1;WORK = 2;}message PhoneNumber {required string number = 1;optional PhoneType type = 2 [default = HOME];}repeated PhoneNumber phone = 4;
}

message消息包含一个或多个编号唯一的字段,每个字段由字段限制,字段类型,字段名和编号四部分组成,字段限制分为:optional(可选的)、required(必须的)以及repeated(重复的)。定义好消息后,使用ProtoBuf编译器生成C++对应的.h和.cc文件,源文件提供了message消息的序列化和反序列化等方法

推荐:

视频讲解:即时通讯项目protobuf 通信协议和序列化协议

C/C++Linux服务器开发/高级架构师群:960994558 群内提供一些免费的C/C++Linux服务器开发/高级架构师学习资料资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等)

C/C++Linux服务器开发/高级架构师 系统学习地址
在这里插入图片描述


http://chatgpt.dhexx.cn/article/bnLZ7JOi.shtml

相关文章

win10商店打不开_win10应用商店闪退是咋回事呢

win10虽然具有闪电般的开机速度,并且还新增了很多功能。但比较是全新的操作系统,所以难免会存在一些故障,这里小编就给大家讲讲win10应用商店闪退打不开怎么解决。 方法一 1,首先,打开开始菜单,进入设置&am…

电脑安装Linux闪退,win10系统运行内置Linux系统闪退如何处理

我们在win10系统电脑的使用中,有小伙伴在Linux系统的使用中出现了问题, win10系统运行内置Linux系统闪退的情况出现了,这是什么原因导致的呢,我们在win10系统运行内置Linux系统闪退如何处理,今天小编就来跟大家分享一下…

Java版mc闪退_本文传授win10运行mc闪退的具体操作对策

我们在使用电脑的时候遇到了win10运行mc闪退问题确实比较难受,要是你的电脑技术没有达到一定的水平,可能就不能解决这个win10运行mc闪退的情况。我们应当如何处理这个问题呢?小编先给大伙说说简单的措施:1、确保电脑中安装了 .NET…

(2022.5.27)【Win10】Windows10重置后微软商店闪退打不开、图片闪退打不开、UWP应用闪退打不开——可能的解决方案

更新日志 20220609 增加注意事项 注意事项 经过多为网友的反馈,目前这个方法是无法直接解决微软商店打不开的问题。因此,基于我目前的了解(6月9日),如果大家遇到这个问题,真的只能重新 U 盘安装系统了。…

win10内置计算机和天气闪退,win10系统中天气闪退怎么办?Win10天气应用闪退问题解决方法...

win10系统中天气闪退怎么办?最近有部分用户在安装了win10系统后发现自带的天气应用出现闪退的情况,点击天气应用,发现它启动了很久,然后就自动关闭了。之后再点击天气应用就闪退,打不开。而尝试打开别的应用却可以正常…

解决WIN10下应用商店不能用,闪退的情况

解决WIN10下应用商店不能用,闪退的情况 先说下我的情况,也是博主手贱,经常看PC上的某个文件或者程序不顺眼的话就会想办法把它干掉,为此重装过几次系统… 这一次是装了win10的周年更新后,烦人的cortana,onedrive等一些我不想要的APP又回来了,在暴力清理这些APP的时候,需要特殊…

win10java闪退怎么办_Win10应用打不开或闪退怎么办?解决方案在此

可能有一些用户升级Win10之后遇到了应用商店、应用打不开或闪退的问题,此时可尝试通过下面的一些方法来解决。 1、点击任务栏的搜索(Cortana小娜)图标,输入Powershell,在搜索结果中右键单击Powershell,选择“以管理员身份运行”。…

win10的c语言程序闪退,Win10专业版软件打不开闪退怎么办?

现在用到最多的Win10系统是Win10专业版,用户重装Win10专业版系统的目的就是为了解决电脑遇到的问题,然而重装系统后还是会出现许许多多的问题,比如说部分软件打不开了,闪退的问题。如果您也遇到了相同的问题,下面就是小…

win10安装虚拟机闪退_win10应用商店战争机器4闪退,无法运行。

创建日期 2018/01/07 win10应用商店战争机器4闪退,无法运行。 日志名称: System 来源: Microsoft-Windows-DistributedCOM 日期: 2018-01-07 14:05:10 事件 ID: 10001 任务类别: 无 级别: 错误 关键字:…

右击计算机管理打开会闪退,win10应用商店为什么会闪退 win10应用商店出故障怎么修复...

win10系统有个应用商店,在商店里用户可以下载一些软件应用,很多用户反馈win10应用商店老是闪退,重启也没有用,这该怎么办?下面小编为大家科普下win10应用商店闪退的解决方案,希望可以帮助到大家。 win10应用…

win10的c语言程序闪退,win10内置应用出现闪退怎么回事? win10打开应用总闪退的解决方法...

Windows10操作系统新增加很多实用的功能,对大家操作电脑有很大帮助。Win10专业版系统自带有相机功能、地图功能、时钟功能,同时还有一个应用商店功能,有的小伙伴说打开内置应用时出现闪退,究竟是哪里出现问题?针对此问…

win10的c语言程序闪退,win10 1909系统出现应用闪退如何解决

许多用户在升级更新到win10 1909版本系统之后,反映说遇到这样一个问题,就是使用应用的时候会出现闪退的现象,该怎么处理呢,下面给大家带来win10 1909系统出现应用闪退的解决措施。 一、重装应用 将闪退的应用卸载之后重新安装一下…

Window10 应用商店闪退问题

新装win10后打开应用商店,搜索软件直接闪退,查看了网上前人留下的经验发现还是没有解决问题,后来点开了电脑的设置 默认是选中第二项,点击第一项后,应用商店可以使用了 当然选中开发人员模式应用商店也是可以使用的

Win10应用商店、应用打不开或闪退的解决方法

越来越多小伙伴都将系统升级成Win10正式版了,win10功能强大令不少朋友感到非常满意,但也有一些朋友升级后却遇到了一些问题,比如应用商店、应用打不开或闪退的问题,今天快启动小编就跟大家介绍Win10应用商店、应用打不开或闪退的解决方法。 1、点击任务栏的搜索(Cortana小娜…

WIN10应用商店(MicrosoftStore)闪退解决方法!!!

本文参考了: CSDN博主「DreamOneDay」的文章https://blog.csdn.net/zyhj2010/article/details/52232749知乎作者千千之雪的文章https://www.zhihu.com/question/31001796/answer/1099015956 本方法适用于:更改过C:\ProgramFiles\WindowsApps权限的用户 如…

win10应用及应用商店闪退有效解决办法

近日遇到win10应用及应用商店闪退问题,在网上找寻各种方法,最终解决,记录下来,供以后查询。 方法 1/步骤1 1、在任务栏的搜索框中输入“Powershell”,然后在搜索结果中找到windows Powershell 鼠标右键单击并选择“以…

第6集丨JavaScript 使用原型(prototype)实现继承——最佳实战3

目录 一、原型继承与属性拷贝1.1 功能说明1.2 功能测试 二、多重继承2.1 功能实现2.2 功能测试 三、寄生式继承四、构造器借用4.1 简单实现4.2 进化版4.2.1 功能实现4.2.2 案例测试 五、借用构造器和原型复制六 综合案例6.1 需求说明6.2 代码实现 一、原型继承与属性拷贝 1.1 功…

Jstorm基础架构

整体架构 深度基于Zookeeper的调度系统。 Jstorm ZK路径 /-{storm.zookeeper.root} -- Jstorm在zookeeper上的根目录,需要在jstorm中配置~/.jstorm/storm.yaml| ||-/nimbus_master -- nimbus_master 的ip和端口| |-/nim…

JStorm使用总结

JStorm 是一个类似Hadoop MapReduce的系统, 用户按照指定的接口实现一个任务,然后将这个任务递交给JStorm系统,JStorm将这个任务跑起来,并且按7 * 24小时运行起来,一旦中间一个Worker 发生意外故障, 调度器…

从0-1实战react项目

文章目录 1. 安装2. 完成一个组件开发3. 添加路由3. 引入element-react1. 运行发现报错./node_modules/element-react/dist/npm/es5/src/locale/format.js2. 接着又报错The <Router /> component appears to be a function component that returns a class instance. Cha…