1.简介

Protocol Buffers是Google开发的一种数据描述语言,能够将数据进行序列化,可用于数据存储、通信协议等方面。

可以理解成更快、更简单、更小的JSON或者XML,区别在于Protocol Buffers是二进制格式,而JSON和XML是文本格式。

相对于XML,Protocol Buffers有如下几个优点:

1.简洁。

2.体积小,消息大小只有XML的1/10到1/3。

3.速度快,解析速度比XML快20~100倍。

4.使用Protocol Buffers的编译器,可以生成更容易在编程中使用的数据访问代码。

5.更好的兼容性,Protocol Buffers设计的一个原则就是要能够很好的支持向下或向上兼容。

使用不同的数据描述语言序列化后的字节个数比对:

使用不同的数据描述语言进行序列化以及反序列化的响应时间比对:

*数据在网络进行传输时要经历三个阶段: 发送方对数据进行序列化、网络中传输、接收方反序列化。

将对象序列化成protobuf、xml、json结构时,protobuf所占的字节数量最少、有效数据的比重最大、总数据最少,因此决定了数据在网络进行传输时所耗费的时间最少。

将对象序列化成protobuf、xml、json结构以及反序列化成对象时,protobuf所耗费的时间最少。

结论:数据使用protobuf序列化格式能够大大提高生产效率(服务的响应时间)。

2.proto文件的语法规则

字段类型

*目前有v2、v3版本,不同版本的语法稍微有些不同,会额外进行说明,以下是v2版本的语法规则。

2.1 消息

1.使用message关键字定义消息,并指定消息的名称(取一个有意义的名字)

2.指定字段的类型和名称

3.添加字段的约束

4.定义字段的编号(从1开始,其中19000~19999被Protocol Buffers作为保留字段)

最基本的message

  1. message User{
  2. required int32 id = 1;
  3. required string username = 2;
  4. required string password = 3;
  5. optional string email = 4;
  6. }

字段约束

required指定该字段必须赋值。

optional表示该字段允许为空,可以使用[default]指定默认值,如果没有指定默认值则会使用字段类型的默认值。

  • 对于strings ,默认是一个空string。
  • 对于bytes ,默认是一个空的bytes。
  • 对于bools ,默认是false。
  • 对于数值类型 ,默认是0。
  • 对于枚举,默认是第一个定义的枚举值,必须为0。

repeated指定字段为集合。

oneof指定一组字段中必须有一个字段要赋值。

*在一个proto文件中可以同时定义多个message类型,生成代码时根据生成代码的目标语言不同,处理的方式不太一样( 对于Java, 每个proto文件都生成一个类,即一个.java文件,每个message、enum类型都是该类的静态内部类 )

  1. message User{
  2. required int32 id = 1;
  3. //username或email之间必须有一个字段要赋值
  4. oneof login{
  5. string username = 3;
  6. string email = 4;
  7. }
  8. required string password = 2;
  9. }
  10.  
  11. message Admin{
  12. required int32 id = 1;
  13. required string username = 2;
  14. required string password = 3;
  15. }

*可以指定字段的类型为其他的message类型。

  1. message Course{
  2. required User user = 1;
  3. required string cour_name = 2;
  4. }
  5.  
  6. message User{
  7. required int32 id = 1;
  8. required string username = 2;
  9. required string password = 3;
  10. optional string email = 4;
  11. }

*在proto文件中支持类型的嵌套,即定义的message类型仅作为包含其message类型的字段类型( 此时Course静态内部类中包含User静态内部类 )

  1. message Course{
  2. message User{
  3. required int32 id = 1;
  4. required string username = 2;
  5. required string password = 3;
  6. optional string email = 4;
  7. }
  8. required User user = 1;
  9. required string cour_name = 2;
  10. }

*使用extensions关键字预留消息类型的字段编号,通过extend关键字继续定义。

  1. message User{
  2. //30~100编号为User类型私有.
  3. extensions 30 to 100
  4. }
  5.  
  6. extend User{
  7. required int32 id = 1;
  8. required string username = 2;
  9. required string password = 3;
  10. optional string email = 4;
  11. }

2.2 枚举

1.使用enum关键字定义枚举,并指定枚举的名称(取一个有意义的名字)

2.设置枚举可能包含的值并定义编号(从1开始,其中19000~19999被Protocol Buffers作为保留字段)

最基本的枚举:

  1. enum Course{
  2. Chinese = ;
  3. Mathematics = ;
  4. English = ;
  5. }

*可以使用import关键字导入其他proto文件。

*可以使用option java_package设置生成java类的包名。

*可以使用option java_outer_classname设置生成java类的类名。

  1. import "other.proto"
  2. option java_package = "com.zht.protobuf";
  3. option java_outer_classname = "UserModel";
  4. message User{
  5. required int32 id = 1;
  6. required string username = 2;
  7. required string password = 3;
  8. optional string email = 4;
  9. }

3.proto2与proto3的不同

1.proto文件的第一行必须使用syntax属性指定使用的protobuf版本:proto2、proto3。

2.移除了 “required” 字段约束。

3.“optional”字段约束改名为 “singular”。

4.在 proto2 中, "optional" 约束可以使用 default 指定字段的默认值(不指定也不赋值则跟随系统), 在 proto3 中, 字段的默认值只能根据字段类型由系统决定。

*当字段被设置为默认值时, 该字段不会被序列化, 提高效率。

5.枚举类型的第一个字段的编号必须为 0 。

4.protobuf的使用

1.环境的准备

在github下载对应操作环境的protobuf工具包: https://github.com/google/protobuf/releases

windows用户选择: protoc-3.5.1-win32.zip

解压后配置环境变量PATH,使其在上下文能直接搜索 protoc.exe。

2.编写.proto文件

E:\proto\user.proto

内容如下:

  1. #v3版本需要在proto文件的第一行使用syntax属性指定proto文件使用的语法的版本
    syntax = "proto2";
  2. option java_package = "com.zht.protobuf";
  3. option java_outer_classname = "UserModel";
  4. message User{
  5. required int32 id = 1;
  6. required string username = 2;
  7. required string password = 3;
  8. optional string email = 4;
  9. }

3.使用protoc.exe命令生成实体

protoc.exe -I [proto文件所在目录] --java_out  [JAVA类存放目录]  [proto文件绝对路径]

4.将实体放入工程进行实体的构造和赋值

将实体放入工程:

构造并且赋值:

  1. public class Main {
  2.  
  3. public static void main(String[] args) throws InvalidProtocolBufferException {
  4. //获取构造器并进行赋值
  5. UserModel.User.Builder builder = UserModel.User.newBuilder();
  6. builder.setId(1);
  7. builder.setUsername("zhuanght");
  8. builder.setPassword("123456");
  9. builder.setEmail("aiuzht119@163.com");
  10.  
  11. //获取实体
  12. UserModel.User user = builder.build();
  13.  
  14. System.out.println("源数据:\r"+ user.toString());
  15. System.out.println("序列化后:"+Arrays.toString(user.toByteArray()));
  16.  
  17. //模拟接收Byte[],反序列化成User实体
  18. byte[] data =user.toByteArray();
  19. User u = User.parseFrom(data);
  20. System.out.println("\r解析:\r" +u.toString());
  21. }
  22.  
  23. }

打印结果 :

  1. 源数据:
  2. id: 1
  3. username: "zhuanght"
  4. password: "123456"
  5. email: "aiuzht119@163.com"
  6.  
  7. 序列化后:[8, 1, 18, 8, 122, 104, 117, 97, 110, 103, 104, 116, 26, 6, 49, 50, 51, 52, 53, 54, 34, 17, 97, 105, 117, 122, 104, 116, 49, 49, 57, 64, 49, 54, 51, 46, 99, 111, 109]
  8.  
  9. 解析:
  10. id: 1
  11. username: "zhuanght"
  12. password: "123456"
  13. email: "aiuzht119@163.com"

  

5.获取序列化后的字节数组在网络中进行传输

5.protobuf实例与json进行转换

导入相关依赖

  1. <dependency>
  2. <groupId>com.googlecode.protobuf-java-format</groupId>
  3. <artifactId>protobuf-java-format</artifactId>
  4. <version>1.4</version>
  5. </dependency>

protobuf实例序列化为json格式

  1. //user为上面例子的UserModel.User消息实例
  2. String json = JsonFormat.printToString(user)

json序列化为protobuf实例

  1. //builder为上面例子的UserModel.User.Builder构造器实例
  2. JsonFormat.merge(json ,builder);
  3. //此时再使用构建器创建的实例就包含转换后的数据
  4. builder.build();

protobuf(quickStart)的更多相关文章

  1. SuperSocket与Netty之实现protobuf协议,包括服务端和客户端

    今天准备给大家介绍一个c#服务器框架(SuperSocket)和一个c#客户端框架(SuperSocket.ClientEngine).这两个框架的作者是园区里面的江大渔. 首先感谢他的无私开源贡献. ...

  2. grpc python quickstart

    参考:grpc python quickstart 准备 1.升级pip $ python -m pip install --upgrade pip 2.安装grpc $ python -m pip ...

  3. python通过protobuf实现rpc

    由于项目组现在用的rpc是基于google protobuf rpc协议实现的,所以花了点时间了解下protobuf rpc.rpc对于做分布式系统的人来说肯定不陌生,对于rpc不了解的童鞋可以自行g ...

  4. Protobuf使用规范分享

    一.Protobuf 的优点 Protobuf 有如 XML,不过它更小.更快.也更简单.它以高效的二进制方式存储,比 XML 小 3 到 10 倍,快 20 到 100 倍.你可以定义自己的数据结构 ...

  5. java netty socket库和自定义C#socket库利用protobuf进行通信完整实例

    之前的文章讲述了socket通信的一些基本知识,已经本人自定义的C#版本的socket.和java netty 库的二次封装,但是没有真正的发表测试用例. 本文只是为了讲解利用protobuf 进行C ...

  6. 在Wcf中应用ProtoBuf替代默认的序列化器

    Google的ProtoBuf序列化器性能的牛逼已经有目共睹了,可以把它应用到Socket通讯,队列,Wcf中,身为dotnet程序员一边期待着不久后Grpc对dotnet core的支持更期待着Wc ...

  7. protobuf的编译安装

    github地址:https://github.com/google/protobuf支持多种语言,有多个语言的版本,本文采用的是在centos7下编译源码进行安装. github上有详细的安装说明: ...

  8. 编译protobuf的jar文件

    1.准备工作 需要到github上下载相应的文件,地址https://github.com/google/protobuf/releases protobuf有很多不同语言的版本,因为我们需要的是ja ...

  9. protobuf学习(2)-相关学习资料

    protobuf官方git地址 protobuf官方英文文档   (你懂的需要FQ) protobuf中文翻译文档 protobuf概述          (官方翻译 推荐阅读) protobuf入门 ...

随机推荐

  1. linux Nagios监控

    监控目标 监控目标主机分为四个部分 硬件资源 操作系统 数据库 应用软件 监控目的: 进行服务器性能调整前,知道调整什么,系统瓶颈在什么地方 被一部分必须同时监控,内容包括吞吐量,反应时间,使用率等 ...

  2. Docker集群编排工具之Kubernetes(K8s)介绍、安装及使用

    K8s基础原理 k8s中文社区:https://www.kubernetes.org.cn/ 简介 Kubernetes与较早的集群管理系统Mesos和YARN相比,对容器尤其是 Docker的支持更 ...

  3. js基本类型与引用类型,浅拷贝和深拷贝

    1. 基本类型: string,number,boolean,null,undefined 2. 引用类型: Function,Array,Object 基本类型:存放在栈内存中的简单数据段,数据大小 ...

  4. freemarker自定义标签报错(七)

    1.错误描述 六月 09, 2014 11:11:09 下午 freemarker.log.JDK14LoggerFactory$JDK14Logger error 严重: Template proc ...

  5. Java中的StringBuffer

    Java中的StringBuffer /** * */ package com.you.model; /** * @author YouHaidong * */ public class StrFoo ...

  6. TypeError: Error #1034: 强制转换类型失败:无法将 "0.49" 转换为 mx.graphics.IFill。

    1.错误描述 TypeError: Error #1034: 强制转换类型失败:无法将 "0.49" 转换为 mx.graphics.IFill. at mx.charts.ser ...

  7. OpenStack_I版 6.Neutron部署

    Neutron是不能自己创建网络的,它需要借助插件才能创建虚拟网桥.网卡 依赖插件 配置ml2为核心插件 本次网络模型采用扁平化网络,不同的网络类型不同的配置,不同的使用方法 打开安全组功能 Linu ...

  8. html 点击复制

    <span>集团登陆:</span> <input readonly id="jituan" type="text" value= ...

  9. jQuery拓展简易快速实现触摸效果

    1.js代码 //触摸开始事件,改变元素的样式 function touchstart(e) { $(this).removeClass("touchend").addClass( ...

  10. Struts2【配置】知识要点

    前言 上篇Struts博文已经讲解了Struts的开发步骤以及执行流程了.....对Struts的配置文件有了了解.....本博文继续讲解Struts在配置的时候一些值得要学习的细节... 通配符 为 ...