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)的语法主要包括以下几个部分:

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

在这里插入图片描述

关键字

Protocol Buffers(Protobuf)的关键字包括:

  1. message:代表实体结构,由多个消息字段(field)组成。
  2. required:表示该字段是必需的。
  3. optional:表示该字段是可选的。
  4. repeated:表示该字段的值是一个列表,可以包含0个或多个元素。
  5. group:用于组织多个字段,但目前该关键字已被废弃,应使用message。
  6. syntax:用于指定协议版本号,没有指定则默认为proto2版本。
  7. package:相等于C++中的命名空间,为了防止名称冲突。
  8. import:引入其他的proto文件,可以使用其他proto文件中定义的消息类型。
  9. message:用于定义消息类型,相当于C++中的struct。
  10. enum:用于定义枚举类型,相当于C++中的enum。
  11. option:用于设置消息字段的选项,如default、packed等。
  12. extensions:用于定义扩展消息字段,可以在现有消息类型的基础上添加新的字段。
  13. rpc:用于定义远程过程调用(RPC)服务。
  14. service:用于定义服务接口。
  15. default :用于为字段设置默认值。
  16. packed :用于指示字段值应该进行压缩存储。
  17. max :用于指定枚举类型的最大值。
  18. value :用于指定枚举类型的值。
  19. returns :用于指定RPC服务的返回类型。

这些关键字在Protobuf中具有特定的含义和用途,根据需要选择使用。

此外,Protobuf中的字段定义包括数据类型、字段名称、字段规则等部分。每个字段的定义由一定的格式构成,包括数据类型、字段名称、字段标识是必须定义的部分,字段默认值部分在proto3版本中不再支持。

在这里插入图片描述

JSON与Protocol Buffers互相转换

  • 与JSON的区别

Protocol Buffers与JSON的区别主要体现在以下三个方面:

  1. 数据格式:JSON是文本格式,而protobuf是二进制格式。JSON数据冗余较大,例如,每条记录都需要包含"CName"和"Gender",据统计,JSON格式的数据至少有20%左右是无效的。而protobuf用二进制编码数据,且数据的格式是事先通过一个后缀名为.proto的文件指定的,因此protobuf的数据信息相对较少。
  2. 解析速度:由于protobuf对message没有动态解析,没有了动态解析的处理序列化速度自然快,通常protobuf的序列化速度是JSON的10倍左右。
  3. 功能: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>
  1. 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字符串
    }
}
  1. 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的简单介绍

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/155004.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

pip 问题

升级pip命令&#xff1a; python -m pip install --upgrade pippip不能下载pytorch&#xff1a; 这个问题我一直没解决。不知道有哪位大佬可以留言给我。把whl文件下载到本地也没有&#xff0c;pip不会进行本地文件夹搜索。

园区网络项目实战

实验背景 某写字楼备搭建一张网络供楼内企业办公使用。写字楼共6层&#xff0c;目前已有三层投入使用&#xff0c;分别 是一层会客大厅、二层行政部及总经理办公室、三层研发部和市场部。一层设有核心机房&#xff0c;其 他各楼层均有一个小房间放置网络设备。 第一步 询…

程序员如何悄悄拔尖,然后惊艳四座?

谁最初还不是个血气方刚、胸怀抱负的有志青年了&#xff1f; 渐渐的&#xff0c;被岁月磨平棱角&#xff0c;被生活冲淡理想&#xff0c;如今的你还有几分似从前&#xff1f; 你是否&#xff0c;不安现状、焦虑未来、忙忙碌碌没有方向&#xff1f; 不甘平庸?不想摸鱼&#…

【LeetCode刷题-滑动窗口】--1004.最大连续1的个数III

1004.最大连续1的个数III 方法&#xff1a;滑动窗口 class Solution {public int longestOnes(int[] nums, int k) {int left 0,right 0,zero 0,res 0;while(right < nums.length){if(nums[right]0){zero;}while(zero > k){if(nums[left] 0){zero--;}left;}res Ma…

深度系统(Deepin)开机无法登录,提示等待一千五百分钟

深度系统&#xff08;Deepin&#xff09;20.0&#xff0c; 某次开机无法登录&#xff0c;提示等待一千五百分钟。 &#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f; 用电脑这么多年&#xff0c;头一回遇到这种…

大数据Doris(二十四):数据导入(Stream Load)介绍

文章目录 数据导入(Stream Load)介绍 一、适用场景 二、基本原理

AE 的软件、硬件、驱动控制、调试策略(没有算法)

#灵感# AE是个值得推敲再推敲的模块&#xff0c;有意思。 目录 相关的硬件-光圈&#xff1a; 相关的软件-曝光-ISO&#xff1a; ISP中的sensor AE 组成&#xff1a; sensor AE的流程及控制&#xff1a; tuning时AE的一些策略&#xff1a; 相关的硬件-光圈&#xff1a; 光…

低代码平台排名及评析一览:谁是最具潜力的Top5?

在数字化时代&#xff0c;低代码平台已经逐渐成为企业快速开发应用的首选工具。众多低代码平台涌现市场&#xff0c;但谁才是最具潜力的Top 5呢&#xff1f;本文将为您揭示并评析这些领先的平台。 云表平台&#xff1a;能开发复杂管理系统的企业级低代码平台 一、平台背景 云表…

Spring Cloud Netflix微服务组件-Hystrix

目录 Hystrix的主要功能 传统容错手段 超时机制 应用容错三板斧 超时机制 舱壁隔离 熔断降级 侵入式Command用法 改进版一&#xff1a;ribbon与hystrix组合 改进版二&#xff1a;feign与hystrix组合 Hystrix三态转换图 源码分析 流程图 核心逻辑流程图 核心实现…

ICCV 23丨3D-VisTA:用于 3D 视觉和文本对齐的预训练Transformer

来源&#xff1a;投稿 作者&#xff1a;橡皮 编辑&#xff1a;学姐 论文链接&#xff1a;https://arxiv.org/abs/2308.04352 开源代码&#xff1a;http://3d-vista.github.io 摘要&#xff1a; 3D视觉语言标定&#xff08;3D-VL&#xff09;是一个新兴领域&#xff0c;旨在将…

【Java 进阶篇】JQuery 遍历:发现元素的魔法之旅

欢迎来到 JQuery 的奇妙世界&#xff0c;一个充满活力和灵感的地方。在这个世界里&#xff0c;我们将一起探讨 JQuery 的遍历功能&#xff0c;这是一个让你轻松发现和操作网页元素的神奇工具。无需太多前端经验&#xff0c;只要有一颗探险的心&#xff0c;你就能在 JQuery 遍历…

一个项目进行测试的一些最基本环境

在一个项目开发到发布的整个过程中&#xff0c;会使用到很多个环境进行测试和运行项目。最基本的开发环境、测试环境、准生产环境、生成环境 一、开发环境 开发环境顾名思义就是我们程序猿自己把项目放到自己的电脑上&#xff0c;配置好以后&#xff0c;跑起来项目&#xff0…

分享6个超绝的设计素材网站,绝对好用!

设计师平时都去哪里找素材呢&#xff1f;收藏好这6个网站&#xff0c;绝对能解决你80%的素材需求&#xff0c;话不多说&#xff0c;直接上干货。 设计素材 1、菜鸟图库 https://www.sucai999.com/?vNTYxMjky 菜鸟图库是一个非常大的素材库&#xff0c;站内包含设计、办公、自…

差分详解(附加模板和例题)

一、一维差分 1.一维差分运用 设a[N]为原数组,b[N]为差分数组&#xff0c;c[N]为进行操作后得到的新数组 (1).先求出差分数组b[N] for(i1;i<n;i) {cin>>a[i];b[i]a[i]-a[i-1]; } (2).进行差分操作&#xff0c;利用void insert(int l,int r,int c)函数 void ins…

MathType2024最新word公式编辑器

使用word进行论文编写时&#xff0c;常需要使用公式编辑器&#xff0c;但有些word中并没有公式编辑器&#xff0c;这时应该怎么办呢&#xff1f;本文将围绕word里没有公式编辑器怎么办&#xff0c;word中的公式编辑器怎么用的内容进行介绍。 一、word里没有公式编辑器怎么办 …

ARM 自动资源管理

Java 7 增加了一个新特性&#xff0c;该特性提供了另外一种管理资源的方式&#xff0c;这种方式能自动关闭文件。这个特性有时被称为自动资源管理(Automatic Resource Management, ARM)&#xff0c; 该特性以 try 语句的扩展版为基础。自动资源管理主要用于当不再需要文件&…

Linux :远程访问的 16 个最佳工具(一)

通过远程桌面协议 (RDP) 可以访问远程 Linux 桌面计算机&#xff0c;这是 Microsoft 开发的专有协议。它为用户提供了一个图形界面&#xff0c;可以通过网络连接连接到另一台/远程计算机。 FreeRDP 是 RDP 的免费实现。 RDP以客户端/服务器模型工作&#xff0c;其中远程计算机必…

echarts双轴右边的轴刻度不显示

图表单轴的时候&#xff0c;yAxis 和 series 是一个对象&#xff0c;但是当双轴显示的时候&#xff0c;yAxis 和 series 就都是一个数组里面包含两个对象&#xff0c;如果是多轴&#xff0c;就是多个对象 看下代码&#xff0c;关键代码 yAxisIndex: 1, 多轴的时候需要指定ind…

大数据架构Lambda-架构师(六十九)

随着信息时代技术的发展&#xff0c;数据量的快速增加逐渐飙升到了惊人的数量级别。并且数据的采集与处理技术还在更新加快。大数据中&#xff0c;结构化占比百分之15左右&#xff0c;其余百分之85都是非结构化数据&#xff0c;他们大量存在于社交网络、互联网和电子商务等领域…
最新文章