【RPC】—Protobuf入门

Protobuf入门

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


Spring专栏👉https://blog.youkuaiyun.com/weixin_53580595/category_12279588.html

SpringMVC专栏👉https://blog.youkuaiyun.com/weixin_53580595/category_12281721.html

Mybatis专栏👉https://blog.youkuaiyun.com/weixin_53580595/category_12279566.html

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

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



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在一定程度上可以保护数据,提升核心数据被破解的门槛,降低核心数据被盗爬的风险(也算是缺点变优点的典型范例)。

Protobuf是一种用于序列化结构化数据的协议,它具有高效、跨平台和可扩展等特点。使用Protobuf,可以定义数据结构和消息类型,并根据这些定义生成对应的代码,用于在不同的应用之间进行数据的传输和存储。在Protobuf中,通过定义message来定义消息类型,类似于C/Java中的class关键字。使用protobuf编译器将.proto文件编译成相应的代码文件后,就可以在代码中使用生成的类进行数据的序列化和反序列化操作。 Protobuf具有广泛的应用场景,特别是在分布式系统和微服务架构中。它可以用于消息传递、持久化存储、RPC通信等各种场景。此外,Protobuf还支持版本演化和向后兼容性,可以满足系统的扩展和升级需求。 如果你想开始学习Protobuf,可以按照以下步骤进行: 1. 下载并安装Protobuf编译器:根据你的操作系统,从Protobuf官方网站下载合适的编译器,并按照官方指南进行安装。 2. 定义消息类型:使用.proto文件定义你的消息结构和消息类型。在文件中使用message关键字定义消息,指定字段名称和类型等信息。 3. 编译.proto文件:使用Protobuf编译器将.proto文件编译成对应的代码文件。根据你的编程语言选择合适的编译选项和目标语言。 4. 在代码中使用生成的类:根据生成的代码文件,在你的代码中使用生成的类进行数据的序列化和反序列化操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一棵___大树

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值