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下面的所有子节点,客户端获取到所有的子节点之后,如果发现自己…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...

【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道
文/法律实务观察组 在债务重组领域,专业机构的核心价值不仅在于减轻债务数字,更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明,合法债务优化需同步实现三重平衡: 法律刚性(债…...

rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...

解析“道作为序位生成器”的核心原理
解析“道作为序位生成器”的核心原理 以下完整展开道函数的零点调控机制,重点解析"道作为序位生成器"的核心原理与实现框架: 一、道函数的零点调控机制 1. 道作为序位生成器 道在认知坐标系$(x_{\text{物}}, y_{\text{意}}, z_{\text{文}}…...

归并排序:分治思想的高效排序
目录 基本原理 流程图解 实现方法 递归实现 非递归实现 演示过程 时间复杂度 基本原理 归并排序(Merge Sort)是一种基于分治思想的排序算法,由约翰冯诺伊曼在1945年提出。其核心思想包括: 分割(Divide):将待排序数组递归地分成两个子…...

边缘计算网关提升水产养殖尾水处理的远程运维效率
一、项目背景 随着水产养殖行业的快速发展,养殖尾水的处理成为了一个亟待解决的环保问题。传统的尾水处理方式不仅效率低下,而且难以实现精准监控和管理。为了提升尾水处理的效果和效率,同时降低人力成本,某大型水产养殖企业决定…...