关于的Protobuf的一些简单整理

公司采用的RPC框架是基于谷歌的gRPC,在后端代码中Request、Response参数和Service服务等都是采用protobuf协议的.proto文件来配置,并编译生成Java代码。Protobuf作为一种重要的序列化和反序列化协议,本文将对其进行整理和总结。

序列化与反序列化

基本概念

程序在运行过程中,数据结构或对象都被存放在内存中,随着程序运行结束,数据结构或对象所占用的内存空间会被回收。

  • 序列化就是把数据结构或对象转换为有序的二进制串,实现持久化到磁盘或者网络传输,序列化后的二进制串保存了数据结构或者对象的状态和相关描述信息,用于对象状态的保存与重建。
  • 反序列化就是将从本地或者网络上获取的序列化后的二进制串转换为数据结构或对象。

当两个进程进行远程通信时,相互之间需要进行数据的传输,例如RPC调用的过程,这就需要服务消费者将服务名称、参数等序列化后经过网络传输到服务提供者,后者将收到的二进制流反序列化后得到服务名称和参数等,进而实现服务等调用。

组件

  • IDL(Interface description language)文件:参与通讯的各方需要对通讯内容做相关约定,为了建立一个与开发语言和平台无关的约定,这个约定也必须由与开发语言和平台无关来描述,用来完成这个描述的就是IDL,接口描述语言,约定文件称为IDL文件。
  • IDL Compiler:为了使得IDL文件约定的内容在各个平台和开发语言中可见,就需要一个编译器,将其转换成各个语言对应的动态库。
  • Stub/Sketleton Lib:负责序列化和反序列化的代码。Stub是部署在分布式系统客户端上的代码,一方面接收应用层的参数,将其序列化后通过底层协议栈发送到服务端;另一方面接收服务端返回的序列化后的数据,将其反序列化后交给应用层。Sketleton部署在服务端,其功能与Stub相反,即从传输层接收来自客户端序列化后的参数,反序列化后交给应用层处理;此外将应用层执行的结果数据序列化后通过底层协议栈发送给客户端。
  • Client/Server:客户端和服务端应用层程序代码。
  • 底层协议栈与互联网:序列化后的数据通过底层的传输层、网络层、数据链路层和物理层转换成数字信号后在互联网中传递。
序列化与反序列化组件

Protobuf

正如Protobuf官网所述,“Protobuf是一种与编程语言和平台无关的用于序列化数据结构的协议”。

语法

使用Protobuf协议时,需要新建.proto文件,定义数据格式,之后编译生成对应语言的代码,例如生成Java类。

1
2
3
4
5
6
7
syntax = "proto3";

message SearchRequest {
string query = 1;
optional int32 page_number = 2;
optional int32 result_per_page = 3;
}

编码