Protobuf入门与使用示例,高性能的序列化框架
source link: https://www.pkslow.com/archives/protobuf-introduction
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
1 前言
首先还是感叹一下谷歌的可怕,做了这么多开创性的生产级别的开源产品, Protobuf
就是其中一员。它是与开发语言无关、与平台无关的结构化数据的序列化框架。支持的语言有 Java
、 C/C++
、 Python
、 Ruby
、 JS
等。使用它序列化后的数据比 Json
和 XML
小很多,所以在网络传输上有更好的性能表现。
但要注意,与 Json
和 XML
不同,人类无法直接或直观地阅读被 Protobuf
序列化后的结果。所以需要通过把接收到的数据反序列化后再通过各自语言处理展示。
2 安装与配置
根据自己的系统,到 Github Release 下载对应的程序,我这里下载的是 protoc-3.13.0-osx-x86_64.zip 。我下载后放在 /Users/larry/Software/protobuf
目录,然后解压:
$ unzip protoc-3.13.0-osx-x86_64.zip
解压后可执行文件就在 bin
目录下。
配置环境变量如下:
export PROTOBUF_HOME=/Users/larry/Software/protobuf export PATH=$PATH:$PROTOBUF_HOME/bin
检查是否已经成功安装和配置:
$ protoc --version libprotoc 3.13.0
正确显示版本号,安装成功。
3 proto文件使用
在 Protobuf
中,用 proto文件
来定义结构化数据,即 Message
。它是非常易于编写的,也简单直观。接下来我们写一个简单的例子。
3.1 编写proto文件
3.1.1 安装插件
我们将编写一个 WebSite.proto
文件,先装一个 Protobuf
的 IDEA
插件,以方便编写及高亮。
3.1.2 编写消息体
我们编写的 proto
文件内容如下:
syntax = "proto3"; option java_package = "com.pkslow.proto"; option java_generate_equals_and_hash = true; option java_outer_classname = "PkslowWebSite"; message WebSite { string name = 1; string link = 2; int32 age = 3; message Server { string hostname = 1; int32 port = 2; } Server server = 4; }
看上是很清晰的:
syntax
指定为 proto3
;
option
可以指定一些配置;
message
是消息体的定义, string
和 int32
这些都是数据类型,后面的数据表示序号,不可重复。
我们还定义了子消息体 Server
,嵌入到 WebSite
中去。
3.1.3 数据类型
数据类型如下:
.proto Type C++ Type Java Type Python Type[2] Go Type Ruby Type C# Type PHP Type Dart Type double double double float float64 Float double float double float float float float float32 Float float float double int32 int32 int int int32 Fixnum or Bignum (as required) int integer int int64 int64 long int/long int64 Bignum long integer/string Int64 uint32 uint32 int int/long uint32 Fixnum or Bignum (as required) uint integer int uint64 uint64 long int/long uint64 Bignum ulong integer/string Int64 sint32 int32 int int int32 Fixnum or Bignum (as required) int integer int sint64 int64 long int/long int64 Bignum long integer/string Int64 fixed32 uint32 int int/long uint32 Fixnum or Bignum (as required) uint integer int fixed64 uint64 long int/long uint64 Bignum ulong integer/string Int64 sfixed32 int32 int int int32 Fixnum or Bignum (as required) int integer int sfixed64 int64 long int/long int64 Bignum long integer/string Int64 bool bool boolean bool bool TrueClass/FalseClass bool boolean bool string string String str/unicode string String (UTF-8) string string String bytes string ByteString str []byte String (ASCII-8BIT) ByteString string List3.1.4 默认值
对于字符串,默认值为空串;
对于字节,默认值为空字节;
对于布尔型,默认值为 false
;
对于数字类型,默认值为 0
;
对于枚举值,默认值为第一个定义的枚举值,其实就是 0
;
对于嵌入式的消息体,不同语言有不同表现。
3.1.5 编译
编写完 proto
文件之后,就可以编译出不同语言对应的类了,我们编译 Java
的类如下:
$ protoc --java_out=./ WebSite.proto
这样在当前目录就会生成 Java
类如下:
3.2 Java使用输出类
前面我们已经编写了 proto
文件,并生成了对应的 Java
类,现在我们来使用它。
我们重新生成 Java
类,直接放在 Java
的目录下:
$ protoc --java_out=../java WebSite.proto
引入依赖如下:
<dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>3.9.2</version> </dependency>
Java
代码及关键注释如下:
package com.pkslow.proto; import com.google.protobuf.InvalidProtocolBufferException; public class ProtobufMain { public static void main(String[] args) { System.out.println("------create message and serialize------"); //创建嵌入式消息类Server PkslowWebSite.WebSite.Server.Builder serverBuilder = PkslowWebSite.WebSite.Server.newBuilder(); PkslowWebSite.WebSite.Server server = serverBuilder.setHostname("1024.511.10.1") .setPort(80) .build(); //创建主消息类WebSite PkslowWebSite.WebSite.Builder webSiteBuilder = PkslowWebSite.WebSite.newBuilder(); PkslowWebSite.WebSite webSite = webSiteBuilder .setName("pkslow") .setLink("www.pkslow.com") .setAge(1) .setServer(server) .build(); //打印结果 System.out.println("webSite: " + webSite); //序列化,可用于网络传输等 byte[] data = webSite.toByteArray(); System.out.println("------deserialize------"); //反序列化 try { PkslowWebSite.WebSite deserializedWebSite = PkslowWebSite.WebSite.parseFrom(data); //打印结果 System.out.println("deserializedWebSite: " + deserializedWebSite); System.out.println("------compare------"); //结果为false,说明是另一个类 System.out.println(webSite == deserializedWebSite); //结果为true,说明序列化和反序列化正确 System.out.println(webSite.equals(deserializedWebSite)); } catch (InvalidProtocolBufferException e) { e.printStackTrace(); } } }
程序执行后的输出日志如下:
------create message and serialize------ webSite: name: "pkslow" link: "www.pkslow.com" age: 1 server { hostname: "1024.511.10.1" port: 80 } ------deserialize------ deserializedWebSite: name: "pkslow" link: "www.pkslow.com" age: 1 server { hostname: "1024.511.10.1" port: 80 } ------compare------ false true
4 总结
本文旨在通过一个从编写到 Java
使用的过程,让大家有一个大概的了解和感性认识。 Protobuf
其实本来也不是什么复杂的东西,但它的应用却是很广的,比如 gRPC
。
项目的代码在: https://github.com/LarryDpk/pkslow-samples
参考资料:
编写 proto3
: 官网Language Guide (proto3)
欢迎关注微信公众号< 南瓜慢说 >,将持续为你更新...
Recommend
-
18
Java默认提供的序列化机制,需要序列化的Java对象只需要实现 Serializable / Externalizable 接口并生成序列化ID,这个类就能够通过 ObjectInput 和 ObjectOutput 序列化和反序列化。 源码:https://github.com/limingios/netFut...
-
7
golang protobuf序列化分析 Lynn_Yuan · 大约5小时之前 · 23 次点击 · 预计阅读时间 4 分钟 · 不到1分钟之前 开始浏览
-
11
Kotlin/Java 列表Protobuf序列化 本来想保存一些Protobuf生成的类的实例到本地,方法自然就是把一个列表的数据序列化成bytes,然后存起来。不过 搞了半天都没办法,于是就自己整了一个 “poor man’s serialization for list of protobuf object”。...
-
1
Java kryo/protobuf/protostuff序列化 or Json 性能对比 发表于 2017-03-02...
-
5
protobuf是怎么序列化的 2022-05-10 后端通用技术 ...
-
1
MMDetection 使用示例:从入门到出门 最近对目标识别感兴趣,想做一些有趣目标识别项目自己玩耍,本来选择的是 YOLOV5 的,但无奈自己使用 YOLOV5 环...
-
1
.net6&7中如何优雅且高性能的使用Json序列化 .net中的S...
-
4
数据序列化工具比较:Avro vs Protobuf 解道Jdon ...
-
2
数据序列化协议 Protocol Buffers(Protobuf) 认知 对每个人而言,真正的职责只有一个:找到自我。然后在心中坚守其一生,全心全意,永不停息。所有其它的路都是不完整的,是人的逃避方式,是对大众理想的懦弱回归,是随波逐流,是对内心的恐惧 ——...
-
4
偶然在网上清华大学电子系科协软件部2023暑期培训的内容中发现了这个东西,后面随着了解发现以后学习有关项目时会用到,便写个随笔记录一下这次学习的经历。作为一种序列化协议,与使用文本方式存储的xml、json不同,protobuf使用的是二进制格式进行存...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK