Protobuf Java 使用案例 入门
protocol buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于(数据)通信协议、数据存储等。
Protocol Buffers 是一种灵活,高效,自动化机制的结构数据序列化方法-可类比 XML,但是比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单。
你可以定义数据的结构,然后使用特殊生成的源代码轻松的在各种数据流中使用各种语言进行编写和读取结构数据。你甚至可以更新数据结构,而不破坏由旧数据结构编译的已部署程序。
Protobuf 最新官网英文文档
https://developers.google.com/protocol-buffers/docs/javatutorial
权威,实时,可靠
Protobuf3 中文文档
https://colobu.com/2017/03/16/Protobuf3-language-guide/
翻译官网文档,缺乏更新,仅供参考
protoc编译器
https://github.com/protocolbuffers/protobuf/releases/
下载带有 linux 或者 windows 字符的压缩包,解压下来进入到bin目录发现一个 protoc 可执行文件
可以使用这个可执行文件进行编译proto文件和输出指定语言格式的类
创建proto文件
syntax = "proto2"; // 语法版本
option java_package = "com.im"; //包名
option java_outer_classname = "Student";//类名,不要跟 message的名称一样!!
message StudentProto {
required int32 id = 1;
optional string name = 2;
}
编译proto文件
./protoc --java_out=./ ./StudentProto.proto
protoc 是编译器二进制文件
--java_out 指定输出的路径
StudentProto.proto proto文件路径
这里默认都是在当前路径完成的
新建maven项目
增加依赖包
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.11.0</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
<version>3.11.0</version>
</dependency>
导入编译的类
将编译后生成的类,放在项目的指定包下
伪代码
这里用的kotlin代码,如果你是用java开发,应该可以看懂的,大部分类似
@Test
fun test01() {
logger.info("本案例测试 protobuf 序列化 和反序列化操作")
val studentBuilder = Student.StudentProto.newBuilder()
studentBuilder.id = 100
studentBuilder.name = "半仙"
val studentProto = studentBuilder.build()
// 将数据写到输出流,如网络输出流,这里就用ByteArrayOutputStream来代替
val output = ByteArrayOutputStream()
studentProto.writeTo(output)
// -------------- 分割线:上面是发送方,将数据序列化后发送 ---------------
val byteArray = output.toByteArray()
logger.info("protobuf 序列化大小:{}", byteArray.size)
val input = ByteArrayInputStream(byteArray)
// 反序列化
val studentProto1 = Student.StudentProto.parseFrom(input)
//to Json
val printer = JsonFormat.printer()
try {
val jsonStudentStr = printer.print(studentProto1)
logger.info("json大小:{}", jsonStudentStr.toByteArray().size)
logger.info("反序列化结果:\n{}", jsonStudentStr)
} catch (e: InvalidProtocolBufferException) {
e.printStackTrace()
}
}
结论
最后运行结果,我们可以看到 protobuf在字节大小是10 json的是35,节省了约2.5倍存储空间
关于ProtoBuf和Json的选型
- Protobuf更容易绑定到对象。比较JSON中的字符串可能很慢。
- 由于JSON是文本形式的,因此其整数和浮点数可能很难编码和解码。
- JSON不是为数字设计的。
- 当您希望数据可读时,JSON很有用。
- 如果您的服务器端应用程序是用JavaScript编写的,那么JSON最有意义。
- 解析JSON字符串,数组和对象需要顺序扫描,这意味着主体的标头没有元素大小或计数。
- 在Protobuf库和JSON中,解析是顺序的。这意味着在相同的CPU和相同的内核上运行格式时,很难显着提高性能。
- 尽管Protobuf的库实现总体看来是一种更快的格式,但它的实现可能并不比JSON快。如果没有将解析器配置为最佳优化,则额外的内存分配或复制会使解析器变慢。
- 相对于JMH基准测试,JSON可能要慢得多。
- 在Protobuf中,整数应该特别快。
- Protofbuf在整数编码方面往往比JSON更快。
- 对于双解码,Protobuf被证明比双解码的JSON快得多(JSON不适合浮点数)。
- 对于网络浏览器直接使用的服务,协议缓冲区为JSON提供了各种优势。
再次,最终,重要的是要同时尝试这两种方法,看看哪种方法对您的特定用例更有利。