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下面的所有子节点,客户端获取到所有的子节点之后,如果发现自己…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...
【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...
