ProtocolBuffers(protobuf)详解
目录
- 前言
- 特点
- 语法定义
- 关键字
- JSON与Protocol Buffers互相转换
- gRPC与Protocol Buffers的关系

前言
Protocol Buffers(通常简称为protobuf)是Google公司开发的一种数据描述语言,它能够将结构化数据序列化,可用于数据存储、通信协议等方面。这种序列化格式很灵活、高效、自动化,不依赖于语言和平台并且可扩展性极强。使用protobuf时,您只需将数据结构定义一次(使用.proto文件定义),便可以使用特别生成的源代码轻松地使用不同的数据流完成对这些结构数据的读写操作,即使使用不同的语言(protobuf的跨语言支持特性)。您甚至可以更新数据结构的定义(就是更新.proto文件内容),而不会破坏依赖“老”格式编译出来的程序。

特点
Protocol Buffers主要具有以下三大特点:
- 语言无关 :支持多种语言,包括但不限于Java、Python、C++、JavaScript、Go、Ruby、PHP、Objective-C、C#等。
- 平台无关 :可生成不同语言的代码并在任何环境中运行。
- 性能好、扩展性好 :序列化和反序列化性能相比 JSON 和 XML 等更快,平均每秒可以处理 10 万条消息。在微服务场景中,使用合适的序列化协议会大大提高系统的性能。

语法定义
Protocol Buffers(Protobuf)的语法主要包括以下几个部分:
- 消息定义:在
.proto文件中定义消息,消息由字段组成。字段有三种类型:required、optional、repeated,分别表示必须、可选和重复。
message Person {required string name = 1;optional int32 id = 2;repeated string email = 3;
}
- 枚举定义:枚举类型允许你定义一组有限的可能的值。
enum PhoneType {MOBILE = 0;HOME = 1;WORK = 2;
}
- 服务定义:服务允许你定义一组相互关联的RPC(远程过程调用)。
service HelloService {rpc SayHello (HelloRequest) returns (HelloReply) {}
}
- 字段编号:每个字段都有一个唯一的数字编号。这是必要的,因为在解析过程中,我们需要知道每个字段的顺序。在
.proto文件中定义的每个字段都有默认值。例如,int32类型的字段默认值为0。 - 字段类型:每个字段都有一个类型。例如,
string、int32、message等。对于message类型的字段,你需要在括号内定义该消息的类型。对于repeated类型的字段,你可以将多个值放入一个列表中。例如,Person消息中的email字段可以包含一个电子邮件地址列表。 - 服务调用:在客户端代码中,你可以使用生成的
stub类来调用服务方法。例如,你可以这样调用SayHello方法:
HelloService.stub stub = HelloServiceGrpc.newBlockingStub(channel);
HelloReply response = stub.sayHello(HelloRequest.newBuilder().build());

关键字
Protocol Buffers(Protobuf)的关键字包括:
- message:代表实体结构,由多个消息字段(field)组成。
- required:表示该字段是必需的。
- optional:表示该字段是可选的。
- repeated:表示该字段的值是一个列表,可以包含0个或多个元素。
- group:用于组织多个字段,但目前该关键字已被废弃,应使用message。
- syntax:用于指定协议版本号,没有指定则默认为proto2版本。
- package:相等于C++中的命名空间,为了防止名称冲突。
- import:引入其他的proto文件,可以使用其他proto文件中定义的消息类型。
- message:用于定义消息类型,相当于C++中的struct。
- enum:用于定义枚举类型,相当于C++中的enum。
- option:用于设置消息字段的选项,如default、packed等。
- extensions:用于定义扩展消息字段,可以在现有消息类型的基础上添加新的字段。
- rpc:用于定义远程过程调用(RPC)服务。
- service:用于定义服务接口。
- default :用于为字段设置默认值。
- packed :用于指示字段值应该进行压缩存储。
- max :用于指定枚举类型的最大值。
- value :用于指定枚举类型的值。
- returns :用于指定RPC服务的返回类型。
这些关键字在Protobuf中具有特定的含义和用途,根据需要选择使用。
此外,Protobuf中的字段定义包括数据类型、字段名称、字段规则等部分。每个字段的定义由一定的格式构成,包括数据类型、字段名称、字段标识是必须定义的部分,字段默认值部分在proto3版本中不再支持。

JSON与Protocol Buffers互相转换
- 与JSON的区别
Protocol Buffers与JSON的区别主要体现在以下三个方面:
- 数据格式:JSON是文本格式,而protobuf是二进制格式。JSON数据冗余较大,例如,每条记录都需要包含"CName"和"Gender",据统计,JSON格式的数据至少有20%左右是无效的。而protobuf用二进制编码数据,且数据的格式是事先通过一个后缀名为.proto的文件指定的,因此protobuf的数据信息相对较少。
- 解析速度:由于protobuf对message没有动态解析,没有了动态解析的处理序列化速度自然快,通常protobuf的序列化速度是JSON的10倍左右。
- 功能:JSON只是一种数据表示法,而protobuf则提供模式(类型),建立文档,强制正确的用法。
总的来说,JSON和protobuf在数据格式、解析速度和功能上存在明显差异。具体选择使用哪种数据存储格式,取决于具体的应用场景和需求。
- 互相转换案例
在Java中,我们可以使用一些库来实现JSON与Protocol Buffers之间的相互转换。这里以Google的Protocol Buffers和Jackson库为例进行介绍。
首先,确保你的项目中已经添加了Protocol Buffers和Jackson的依赖。如果你使用Maven,可以在pom.xml文件中添加以下依赖:
<dependencies><!-- Protocol Buffers --><dependency><groupId>com.google.protobuf</groupId><artifactId>protobuf-java</artifactId><version>3.17.3</version> <!-- 请检查是否有更新的版本 --></dependency><!-- Jackson --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.13.0</version> <!-- 请检查是否有更新的版本 --></dependency>
</dependencies>
- Protocol Buffers转JSON
首先,我们需要将Protocol Buffers的消息转换为Java对象。假设我们有一个Person消息:
syntax = "proto3";
package tutorial;message Person {string name = 1;int32 id = 2;string email = 3;
}
编译这个.proto文件,生成Java代码。然后,我们可以使用Jackson库将Java对象转换为JSON:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.protobuf.util.JsonFormat;
import tutorial.PersonOuterClass.Person;public class ProtobufToJsonExample {public static void main(String[] args) throws Exception {Person person = Person.newBuilder().setId(1234).setName("Alice").setEmail("alice@example.com").build();ObjectMapper objectMapper = new ObjectMapper();String jsonString = JsonFormat.printer().print(person);System.out.println(jsonString); // 输出JSON字符串}
}
- JSON转Protocol Buffers
同样地,我们可以将JSON字符串转换为Java对象后,再将其转换为Protocol Buffers消息:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.protobuf.util.JsonFormat;
import tutorial.PersonOuterClass.Person;public class JsonToProtobufExample {public static void main(String[] args) throws Exception {String jsonString = "{\"id\":1234,\"name\":\"Alice\",\"email\":\"alice@example.com\"}";ObjectMapper objectMapper = new ObjectMapper();Person person = objectMapper.readValue(jsonString, Person.class);System.out.println(person); // 输出Person消息对象}
}
在Java中使用Protocol Buffers可以方便地进行数据序列化和反序列化。以下是一个简单的使用案例:
假设我们有一个Person消息类型,包含姓名、年龄和电子邮件地址等字段。我们可以使用Protocol Buffers的Java API来序列化和反序列化这个消息类型。
首先,我们需要定义Person消息类型的.proto文件,如下所示:
syntax = "proto3";package tutorial;message Person {string name = 1;int32 age = 2;string email = 3;
}
然后,我们需要使用Protocol Buffers的编译器protoc将.proto文件编译成Java代码。命令如下:
protoc --java_out=./ ./person.proto
这将生成一个PersonOuterClass.java和一个Person.java文件,其中Person.java包含Person消息类型的定义和相关方法。我们可以将这些代码导入到我们的Java应用程序中。
接下来,我们可以使用Java代码来序列化和反序列化Person消息类型。以下是一个简单的例子:
import tutorial.PersonOuterClass.Person;
import com.google.protobuf.util.JsonFormat;public class PersonProtobufExample {public static void main(String[] args) throws Exception {// 创建一个Person对象Person person = Person.newBuilder().setId(1234).setName("Alice").setEmail("alice@example.com").build();// 将Person对象序列化为字节数组byte[] bytes = person.toByteArray();// 将字节数组反序列化为Person对象Person deserializedPerson = Person.parseFrom(bytes);// 输出反序列化后的Person对象System.out.println(deserializedPerson);}
}
这个例子中,我们创建了一个Person对象,将其序列化为字节数组,然后将字节数组反序列化为Person对象,并输出反序列化后的Person对象。
gRPC与Protocol Buffers的关系
Protocol Buffers(protobuf)是由 Google 开发的一种数据序列化协议(类似于 XML、JSON、YAML 等),它可以将结构化的数据序列化成字节流,以便在网络上进行传输或存储到文件或数据库中。
gRPC 是一个高性能、开源、通用的 RPC(远程过程调用)框架,它基于 protobuf 实现,使用 protobuf 序列化协议来序列化和反序列化消息。gRPC 支持多种语言,包括 Java、C++、Python、Go、Ruby、PHP 等,可以跨语言进行通信。
因此,gRPC 和 Protocol Buffers 的关系是,protobuf 是 gRPC 使用的一种数据序列化协议,gRPC 利用 protobuf 将数据序列化成字节流,以便在网络上进行传输或存储到文件或数据库中。同时,gRPC 也提供了接口和工具,使得用户可以方便地使用 protobuf 进行数据序列化和反序列化操作。
gRPC的简单介绍

相关文章:
ProtocolBuffers(protobuf)详解
目录 前言特点语法定义关键字JSON与Protocol Buffers互相转换gRPC与Protocol Buffers的关系 前言 Protocol Buffers(通常简称为protobuf)是Google公司开发的一种数据描述语言,它能够将结构化数据序列化,可用于数据存储、通信协议…...
HTTP 到 HTTPS 再到 HSTS 的转变
近些年,随着域名劫持、信息泄漏等网络安全事件的频繁发生,网站安全也变得越来越重要,也促成了网络传输协议从 HTTP 到 HTTPS 再到 HSTS 的转变。 HTTP HTTP(超文本传输协议) 是一种用于分布式、协作式和超媒体信息系…...
清华学霸告诉你:如何自学人工智能?
清华大学作为中国顶尖的学府之一,培养了许多优秀的人才,其中不乏在人工智能领域有所成就的学霸。通过一位清华学霸的经验分享,揭示如何自学人工智能,帮助你在这场科技浪潮中勇往直前。 一、夯实基础知识 数学基础:学习…...
Ubuntu 安装VMware Tools选项显示灰色,如何安装VMware Tools
切换apt源为阿里云: https://qq742971636.blog.csdn.net/article/details/134291339 只要你的网络没问题,你直接执行这几个命令,重启ubuntu虚拟机即可、 sudo dpkg --configure -a sudo apt-get autoremove open-vm-tools sudo apt-get ins…...
SpringBoot 2.x 实战仿B站高性能后端项目
SpringBoot 2.x 实战仿B站高性能后端项目 下栽の地止:请看文章末尾 通常SpringBoot新建项目,默认是集成了Maven,然后所有内容都在一个主模块中。 如果项目架构稍微复杂一点,就需要用到Maven多模块。 本文简单概述一下,…...
vscode文件夹折叠问题
今天发现一个vscode的文件夹显示的问题,首先是这样的,就是我的文件夹里又一个子文件夹,子文件夹里有一些文件,但是我发现无法折叠起这个子文件夹,总是显示全部的文件,这让我备份很难,具体参考 h…...
4-flask-cbv源码、Jinja2模板、请求响应、flask中的session、flask项目参考
1 flask中cbv源码 2 Jinja2模板 3 请求响应 4 flask中的session 5 flask项目参考 1 flask中cbv源码 ***flask的官网文档:***https://flask.palletsprojects.com/en/3.0.x/views/1 cbv源码执行流程1 请求来了,路由匹配成功---》执行ItemAPI.as_view(item…...
2.Pandas数据预处理
2.1 数据清洗 以titanic数据为例。 df pd.read_csv(titanic.csv) 2.1.1 缺失值 (1)缺失判断 df.isnull() (2)缺失统计 # 列缺失统计 df.isnull().sum(axis0) # 行缺失统计 df.isnull().sum(axis1) # 统计缺失率 df.isnu…...
C# IEnumerable<T>介绍
IEnumerable 是 C# 中的一个接口,它是 .NET Framework 中的集合类型的基础。任何实现了 IEnumerable 接口的对象都可以进行 foreach 迭代。 IEnumerable 只有一个方法,即 GetEnumerator,该方法返回一个 IEnumerator 对象。IEnumerator 对象用…...
九洲
《九洲》 作者/罗光记 九洲春色映朝阳, 洲渚风光似画廊。 柳絮飘飞花似雪, 九州繁华共锦裳。 水波荡漾鱼儿跃, 洲边鸟语唤晨光。 春风拂过千里岸, 九洲儿女笑语扬。...
基于Genio 700 (MT8390)芯片的AR智能眼镜方案
AR眼镜是一种具有前所未有发展机遇的设备,无论是显示效果、体积还是功能都有明显的提升。AR技术因其智能、实时、三维、多重交互和开放世界的特点备受关注。 AR眼镜集成了AR技术、语音识别、智能控制等多项高科技功能,可以帮助用户实现更加便捷、高效、个…...
锐捷OSPF认证
一、知识补充 1、基本概述 OSPF区域认证和端口认证是两种不同的认证机制,用于增强OSPF协议的安全性。 OSPF区域认证(OSPF Area Authentication):这种认证机制是基于区域的。在OSPF网络中,每个区域都可以配置一个区域…...
M2 Mac Xcode编译报错 ‘***.framework/‘ for architecture arm64
In /Users/fly/Project/Pods/YYKit/Vendor/WebP.framework/WebP(anim_decode.o), building for iOS Simulator, but linking in object file built for iOS, file /Users/fly/Project/Pods/YYKit/Vendor/WebP.framework/WebP for architecture arm64 这是我当时编译模拟器时报…...
Python算法题2023 输出123456789到98765432中完全不包含2023的数有多少
题目: 无输入,只需输出结果🤐 这个数字比较大,小伙伴们运行的时候要给代码一点耐心嗷つ﹏⊂ ,下面是思路,代码注释也很详细,大致看一下吧(^∀^●)…...
SpringBoot整合Thymeleaf
Thymeleaf 支持 HTML 原型,可以让前端工程师在浏览器中直接打开查看样式,也可以让后端工程师结合真实数据查看显示效果 Thymeleaf 除了展示基本的 HTML ,进行页面渲染之外,也可以作为一个 HTML 片段进行渲染,例如我们在…...
OpenAI的多函数调用(Multiple Function Calling)简介
我在六月份写了一篇关于GPT 函数调用(Function calling) 的博客https://blog.csdn.net/xindoo/article/details/131262670,其中介绍了函数调用的方法,但之前的函数调用,在一轮对话中只能调用一个函数。就在上周,OpenAI…...
在国内购买GPT服务前的一定要注意!!!
本人已经入坑GPT多日,从最开始的应用GPT到现在的自己研发GPT,聊聊我对使用ChatGPT的一些思考,有需要使用GPT的朋友或者正在使用GPT的朋友,一定要看完这篇文章,可能会比较露骨,也算是把国内知识库、AI的套路…...
Redis新操作
1.Bitmaps 1.1概述 Bitmaps可以对位进行操作,实际上它就是一个字符串,可以将Bitmaps想象为一个以位为单位的数组,数组中的每个元素只能存储0或者1,数组的下标在Bitmaps被称为偏移量。 setbit key offset value:设置o…...
Panda3d 外部硬件接口介绍
Panda3d 外部硬件接口介绍 文章目录 Panda3d 外部硬件接口介绍键盘支持(Keyboard Support)轮询接口击键事件原始键盘事件鼠标支持(Mouse Support)鼠标模式绝对鼠标模式相对鼠标模式受限鼠标模式验证鼠标模式多个鼠标(Multiple Mice )Linux 下的多个鼠标(Multiple Mice u…...
解决Redis分布式锁宕机出现不可靠问题-zookeeper分布式锁
核心思想:当客户端要获取锁,则创建节点,使用完锁,则删除该节点。 客户端获取锁时,在 lock 节点下创建临时顺序节点。然后获取 lock下面的所有子节点,客户端获取到所有的子节点之后,如果发现自己…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
