Protocol Buffers一种结构化数据存储格式。特点:快、小
序列化空间开销
解析耗时性能
小结:根据上图测评,序列化后的空间开销与解析性能上,Avro与Protobuf不相上下独占鳌头;另外根据“Protobuf协议介绍及性能实测”文中测评来看,报文在几千个字节以内,Protobuf与JSON/XML并没有太大优势,而hessian2表现更优秀;当报文大小超过10万字节,Protobuf性能是XML的3倍,是JSON的2倍,Hessian2的2倍;当报文大小超过10万字节,序列化后的字节大小约XML的1/4,约JOSN的1/2,约Hessian2的1/3;高性能原因Protobuf优化的二进制消息格式,JSON/XML是文本描述的;适用于性能要求高的RPC调用。
二、使用指南1.定义.proto文件以下面addressbook.proto为例来看下.proto的语法。
syntax = "proto3"; // @1 package tutorial; // @2 import "google/protobuf/timestamp.proto"; // @3 option java_package = "com.example.tutorial"; // @4 option java_outer_classname = "AddressBookProtos"; // @5 message Person { // @6 string name = 1; // @7 int32 id = 2; // @8 string email = 3; enum PhoneType { // @9 MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { string number = 1; PhoneType type = 2; } repeated PhoneNumber phones = 4; // @10 google.protobuf.Timestamp last_updated = 5; // @11 } message AddressBook { // @12 repeated Person people = 1; // @13 }代码备注 @1 定义proto的版本 @2 定义proto的包名 @3 导入其他的.proto文件 @4 option可选的;指java类生成所在的包,如果没有指定包名采用默认包名 @5 option可选的;指生成的class类名,如果没有指定根据.profo文件名称驼峰命名 @6 定义消息类型,定义Person的消息格式 @7 定义字段类型string @8 定义字段类型整型 @9 定义枚举类型,枚举类型需整型值范围 @10 表示该值可重复,详单于java中的list @11 引用的时间类型生成的代码为:com.google.protobuf.Timestamp lastUpdated_ @12 定义消息类型,定义AddressBook的消息格式 @13 表示该值可重复,相当于Java中List
定义一个Service
service SoaInvokerService { rpc call (SoaInvokerRequest) returns (SoaInvokerResponse); }备注:定义一个消息类型SoaInvokerService用在RPC的调用中。编译器会根据不同的语言生成不同的服务代码与存根。上面Service在通过编译器Java会生成SoaInvokerService的抽象类及存根。
2.编译.proto文件
通过下面命令生成Java代码,编译器为为每个消息类型生成一个.java文件以及特殊的Build类用于创建该类实例的接口。
bin/protoc --java_out=output example/addressbook.proto使用方式
Person person = Person.newBuilder() .setId(1) .setName("zhansan") .build(); // @1 person.toByteArray(); // @2 Person.parseFrom(byte[] data); // @3 person.writeTo(OutputStream out); // @4 Person.parseFrom(InputStream input) // @5 Person.Builder personBuilder = Person.newBuilder(); personBuilder.mergeFrom(); // @6代码备注 @1 使用了Builder设计模式构建对象 @2 将消息对象Person序列化为byte数组 @3 将byte数组转换为消息对象Person @4 序列化该消息对象Person并写入到OutputStream @5 从InputStream读取并解析成消息对象Person @6 将同类消息merge到一起 备注:编译器下载地址:https://github.com/protocolbuffers/protobuf/releases
3.读写数据写数据
AddressBook.Builder addressBook = AddressBook.newBuilder(); addressBook.addPeople( PromptForAddress(new BufferedReader(new InputStreamReader(System.in)), System.out)); // @1 FileOutputStream output = new FileOutputStream(args[0]); addressBook.build().writeTo(output); // @2代码备注 @1 添加People到地址本 @2 通过writeTo方法将消息地址本写到到本地文件中
存储内容:address.store
strings address.store zhansan zhanshan@126.com" 13113133421读数据
AddressBook addressBook = AddressBook.parseFrom(new FileInputStream(args[0])); // @1 for (Person person: addressBook.getPeopleList()) { System.out.println("Person ID: " + person.getId()); System.out.println(" Name: " + person.getName()); }@1 通过parseFrom将输入流转换为AddressBook消息对象
内容输出
Person ID: 1 Name: zhansan E-mail address: zhanshan@126.com Mobile phone #: 13113133421 Person ID: 2 Name: lisi E-mail address: lisi@126.com Mobile phone #: 13164140909示例代码 https://github.com/protocolbuffers/protobuf/tree/master/examples
三、本文总结本文根据测评结果,简单分析了Protocol Buffers的亮点:快、小;以及protobuf编译工具的使用;编译工具生成Java代码消息对象方法的使用;通过示例解读了生成二进制消息格式的读写方式。
四、参考资料1.[译]Protobuf 语法指南 https://colobu.com/2015/01/07/Protobuf-language-guide/ 2.Protocol Buffers指南 https://developers.google.com/protocol-buffers/docs/javatutorial?hl=zh-cn 3.protobuf协议介绍及性能实测 https://lupeier.com/post/protobuf-introduce-and-test/ 4.序列化和反序列化 https://tech.meituan.com/2015/02/26/serialization-vs-deserialization.html ---来自腾讯云社区的---瓜农老梁
微信扫一扫打赏
支付宝扫一扫打赏