当前位置: 首页 > news >正文

【RPC】—Protobuf入门

Protobuf入门

⭐⭐⭐⭐⭐⭐
Github主页👉https://github.com/A-BigTree
笔记链接👉https://github.com/A-BigTree/Code_Learning
⭐⭐⭐⭐⭐⭐


Spring专栏👉https://blog.csdn.net/weixin_53580595/category_12279588.html

SpringMVC专栏👉https://blog.csdn.net/weixin_53580595/category_12281721.html

Mybatis专栏👉https://blog.csdn.net/weixin_53580595/category_12279566.html

如果可以,麻烦各位看官顺手点个star~😊

如果文章对你有所帮助,可以点赞👍收藏⭐支持一下博主~😆


文章目录

  • Protobuf入门
    • 1 前言
    • 2 什么是Protocol Buffer
      • 2.1 技术背景
      • 2.2 Protobuf在谷歌业务中的地位
    • 3 Protocol协议的消息定义
    • 4 Protobuf的代码生成
    • 5 Protobuf的优点
      • 5.1 效率高
      • 5.2 支持跨平台、多语言
      • 5.3 扩展性、兼容性好
      • 5.4 使用简单
    • 6 Protobuf的缺点


1 前言

在IM应用中,优化数据流量消耗过多的基本方法就是使用高度压缩的通讯协议,而数据压缩后流量减小带来的自然结果也就是省电:因为大数据量的传输必然需要更久的网络操作、数据序列化及反序列化操作,这些都是电量消耗过快的根源。

当前IM应用中最热门的通讯协议无疑就是Google的Protobuf了,基于它的优秀表现,微信和手机QQ这样的主流IM应用也早已在使用它。

2 什么是Protocol Buffer

什么是 Google Protocol Buffer?

Google Protocol Buffer(简称 Protobuf)是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 个 .proto 文件。他们常用于 RPC 系统和持续数据存储系统等应用场景。

实际上: Protocol Buffers(简称 Protobuf)是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。

目前: Protobuf官方工程主页上显示的已支持的开发语言多达10种,分别有:C++、Java、Python、Objective-C、C#、Ruby、Go、PHP、Dart、Javascript,基本上主流的语言都已支持(具体详见Protobuf工程主页:https://github.com/protocolbuffers/protobuf)。

Protobuf数据类型与其他语言的对照:

.proto TypeC++ TypeJava/Kotlin Type[1]Python Type[3]Go TypeRuby TypeC# TypePHP TypeDart Type
doubledoubledoublefloatfloat64Floatdoublefloatdouble
floatfloatfloatfloatfloat32Floatfloatfloatdouble
int32int32intintint32Fixnum or Bignum (as required)intintegerint
int64int64longint/longint64Bignumlonginteger/stringInt64
uint32uint32intint/longuint32Fixnum or Bignum (as required)uintintegerint
uint64uint64longint/longuint64Bignumulonginteger/stringInt64
sint32int32intintint32Fixnum or Bignum (as required)intintegerint
sint64int64longint/longint64Bignumlonginteger/stringInt64
fixed32uint32intint/longuint32Fixnum or Bignum (as required)uintintegerint
fixed64uint64longint/longuint64Bignumulonginteger/stringInt64
sfixed32int32intintint32Fixnum or Bignum (as required)intintegerint
sfixed64int64longint/longint64Bignumlonginteger/stringInt64
boolboolbooleanboolboolTrueClass/FalseClassboolbooleanbool
stringstringStringstr/unicodestringString (UTF-8)stringstringString
bytesstringByteStringstr (Python 2) bytes (Python 3)[]byteString (ASCII-8BIT)ByteStringstringList

2.1 技术背景

Protobuf最先开始是 Google用来解决索引服务器 request/response 协议的。在没有Protobuf之前,Google 已经存在了一种 request/response 格式,用于手动处理 request/response 的编解码。

如果是非常明确的格式化协议,会使新协议变得非常复杂。因为开发人员必须确保请求发起者与处理请求的实际服务器之间的所有服务器都能理解新协议,然后才能切换开关以开始使用新协议。这也就是每个服务器开发人员都遇到过的低版本兼容、新旧协议兼容相关的问题。为了解决这些问题,于是Protobuf就诞生了。

2.2 Protobuf在谷歌业务中的地位

Protobuf 现在是 Google 用于数据交换和存储的通用语言。谷歌代码树中定义了 48162 种不同的消息类型,包括12183个 .proto 文件。它们既用于 RPC 系统,也用于在各种存储系统中持久存储数据。

Protobuf 诞生之初是为了解决服务器端新旧协议(高低版本)兼容性问题,名字也很体贴——“协议缓冲区”,只不过后期慢慢发展成用于传输数据。

3 Protocol协议的消息定义

Protobuf 的消息是在idl文件(.proto)中描述的。

syntax = "proto3";package domain;option java_package = "com.Protobuf.generated.domain";
option java_outer_classname = "CustomerProtos";message Customers {repeated Customer customer = 1;
}message Customer {int32 id = 1;string firstName = 2;string lastName = 3;enum EmailType {PRIVATE = 0;PROFESSIONAL = 1;}message EmailAddress {string email = 1;EmailType type = 2;}repeated EmailAddress email = 5;
}

上面的消息比较简单,Customers包含多个CustomerCustomer包含一个id字段、一个firstName字段、一个lastName字段以及一个email的集合)。

除了上述定义外,文件顶部还有三行可帮助代码生成器的声明:

  • syntax = "proto3":用于idl语法版本,目前有两个版本proto2和proto3,两个版本语法不兼容,如果不指定,默认语法是proto2(由于proto3比proto2支持的语言更多,语法更简洁,本文使用的是proto3);
  • package domain:此配置用于嵌套生成的类/对象;
  • option java_package:生成器还使用此配置来嵌套生成的源(此处的区别在于这仅适用于Java,在使用Java创建代码和使用JavaScript创建代码时,使用了两种配置来使生成器的行为有所不同。也就是说,Java类是在包com.Protobuf.generated.domain下创建的,而JavaScript对象是在包domain下创建的);

4 Protobuf的代码生成

首先安装 Protobuf 编译器 protoc(点这里有详细的安装教程)。

安装完成后,可以使用以下命令生成 Java 源代码:

protoc --java_out=./src/main/java ./src/main/idl/customer.proto

**上述命令的意图是:**从项目的根路径执行该命令,并添加了两个参数 java_out(即定义 ./src/main/java/ 为Java代码的输出目录;而 ./src/main/idl/customer.proto.proto文件所在目录)。

生成的代码很复杂,但用法却很简单:

CustomerProtos.Customer.EmailAddress email = CustomerProtos.Customer.EmailAddress.newBuilder().setType(CustomerProtos.Customer.EmailType.PROFESSIONAL).setEmail("crichardson@email.com").build();CustomerProtos.Customer customer = CustomerProtos.Customer.newBuilder().setId(1).setFirstName("Lee").setLastName("Richardson").addEmail(email).build();
// 序列化
byte[] binaryInfo = customer.toByteArray();
System.out.println(bytes_String16(binaryInfo));
System.out.println(customer.toByteArray().length);
// 反序列化
CustomerProtos.Customer anotherCustomer = CustomerProtos.Customer.parseFrom(binaryInfo);
System.out.println(anotherCustomer.toString());

5 Protobuf的优点

5.1 效率高

从序列化后的数据体积角度,与XML、JSON这类文本协议相比,Protobuf通过 T-(L)-V(TAG-LENGTH-VALUE)方式编码,不需要", {, }, :等分隔符来结构化信息。同时在编码层面使用varint压缩。

所以描述同样的信息,Protobuf序列化后的体积要小很多,在网络中传输消耗的网络流量更少,进而对于网络资源紧张、性能要求非常高的场景。比如在移动网络下的IM即时通讯应用中,Protobuf协议就是非常不错的选择。

从序列化/反序列化速度角度,与XML、JSON相比,Protobuf序列化/反序列化的速度更快,比XML要快20-100倍。

5.2 支持跨平台、多语言

Protobuf是平台无关的,无论是Android、iOS、PC,还是C#与Java,都可以利用Protobuf进行无障碍通讯。

5.3 扩展性、兼容性好

Protobuf具有向后兼容的特性:更新数据结构以后,老版本依旧可以兼容,这也是Protobuf诞生之初被寄予解决的问题,因为编译器对不识别的新增字段会跳过不处理。

5.4 使用简单

Protobuf 提供了一套编译工具,可以自动生成序列化、反序列化的样板代码,这样开发者只要关注业务数据idl,简化了编码解码工作以及多语言交互的复杂度。

6 Protobuf的缺点

  • 不具备自描述能力:跟XML、JSON相比,这两者是自描述的,而ProtoBuf则不是;
  • 数据可读性非常差:ProtoBuf是二进制协议,如果没有idl文件,就无法理解二进制数据流,对调试非常不友好;

由于没有idl文件无法解析二进制数据流,ProtoBuf在一定程度上可以保护数据,提升核心数据被破解的门槛,降低核心数据被盗爬的风险(也算是缺点变优点的典型范例)。

http://www.lryc.cn/news/94494.html

相关文章:

  • 【⑩MySQL】:表管理,让数据管理不再困难
  • Springboot项目使用原生Websocket
  • 在Vue 3中如何实现服务端渲染(SSR)
  • 【计算机组成原理期末课设作业】16位微型计算机实现——MOVS串传送扩展指令设计
  • CodeMirror 对 XML 文档熟悉及元素控制自定义
  • Jetpack - ViewModel
  • 【新版系统架构】第十三章-层次式架构设计理论与实践
  • 剖析Linux文件系统
  • 简介Maven结构与配置方法
  • 好用的网址6
  • MySQL数据库---笔记5
  • Yocto:初始
  • autodl算力租用平台应用于pycharm
  • 高德地图的使用
  • <List<Map<String,String>>> 删除元素常见的误区以及删除方法
  • Linux下的编辑器——vim的简单上手指南
  • C++多线程学习(二、多线程的几种创造方式【有返回值的之后讲】)
  • 前端开发框架生命周期详解:Vue、React和Angular
  • 【Java从入门到大牛】程序流程控制
  • UML学习统一建模语言
  • 【C++学习笔记】RAII思想——智能指针
  • ubantu配置python环境
  • 单向/双向V2G环境下分布式电源与电动汽车充电站联合配置方法(matlab代码)
  • dockerfile常用指令
  • Matlab/simulink与dsp28335联合开发教程
  • 新项目搞完啦!!!
  • 分享一个可交互的小场景(二)
  • 2.5 DNS 应用 -- 1. DNS 概述
  • 基于STM32麦克风阵列音频信号处理系统设计
  • 《重构》:Extract Class and Inline Class