Google Protocol Buffer(简称 Protobuf)是一种轻便高效的结构化数据存储格式,平台无关、语言无关、可扩展,可用于通讯协议和数据存储等领域。

数据交互xml、json、protobuf格式比较

1、json: 一般的web项目中,最流行的主要还是json。因为浏览器对于json数据支持非常好,有很多内建的函数支持。

2、xml: 在webservice中应用最为广泛,但是相比于json,它的数据更加冗余,因为需要成对的闭合标签。json使用了键值对的方式,不仅压缩了一定的数据空间,同时也具有可读性。

3、protobuf : 是后起之秀,是谷歌开源的一种数据格式,适合高性能,对响应速度有要求的数据传输场景。因为profobuf是二进制数据格式,需要编码和解码。数据本身不具有可读性。因此只能反序列化之后得到真正可读的数据。相对于其它protobuf更具有优势

1:序列化后体积相比Json和XML很小,适合网络传输

2:支持跨平台多语言

3:消息格式升级和兼容性还不错

4:序列化反序列化速度很快,快于Json的处理速速

protoBuf的优点

Protobuf 有如 XML,不过它更小、更快、也更简单。你可以定义自己的数据结构,然后使用代码生成器生成的代码来读写这个数据结构。你甚至可以在无需重新部署程序的情况下更新数据结构。只需使用 Protobuf 对数据结构进行一次描述,即可利用各种不同语言或从各种不同数据流中对你的结构化数据轻松读写。它有一个非常棒的特性,即“向后”兼容性好,人们不必破坏已部署的、依靠“老”数据格式的程序就可以对数据结构进行升级。

Protobuf 语义更清晰,无需类似 XML 解析器的东西(因为 Protobuf 编译器会将 .proto 文件编译生成对应的数据访问类以对 Protobuf 数据进行序列化、反序列化操作)。使用 Protobuf 无需学习复杂的文档对象模型,

Protobuf 的编程模式比较友好,简单易学,同时它拥有良好的文档和示例,对于喜欢简单事物的人们而言,Protobuf 比其他的技术更加有吸引力。

ProtoBuf 的不足

Protobuf 与 XML 相比也有不足之处。它功能简单,无法用来表示复杂的概念。XML 已经成为多种行业标准的编写工具,Protobuf 只是 Google 公司内部使用的工具,在通用性上还差很多。 由于文本并不适合用来描述数据结构,所以 Protobuf 也不适合用来对基于文本的标记文档(如 HTML)建模。另外,由于 XML 具有某种程度上的自解释性,它可以被人直接读取编辑,在这一点上Protobuf 不行,它以二进制的方式存储,除非你有 .proto 定义,否则你没法直接读出 Protobuf 的任何内容

Protobuf安装

安装protoBuf

#下载 protoBuf:
$ git clone https://github.com/protocolbuffers/protobuf.git
#安装依赖库
$ sudo apt-get install autoconf automake libtool curl make g++ unzip libffidev
-y
#安装
$ cd protobuf/
$ ./autogen.sh
$ ./configure
$ make
$ sudo make install
$ sudo ldconfig # 刷新共享库
#成功后需要使用命令测试
$ protoc –h

获取 proto包

#Go语言的proto API接口
$ go get -v -u github.com/golang/protobuf/proto

安装protoc-gen-go插件

#安装
$ go get -v -u github.com/golang/protobuf/protoc-gen-go
#编译
$ cd $GOPATH/src/github.com/golang/protobuf/protoc-gen-go/
$ go build
#将生成的 protoc-gen-go可执行文件,放在/bin目录下
$ sudo cp protoc-gen-go /bin/

protobuf的语法

定义一个消息类型

syntax = "proto3";

message PandaRequest {
string name = ;
int32 shengao = ;
repeated int32 tizhong = ;
}

PandaRequest消息格式有3个字段,在消息中承载的数据分别对应于每一个字段。其中每个字段都有一个名字和一种类型。

文件的第一行指定了你正在使用proto3语法:如果你没有指定这个,编译器会使用proto2。这个指定语法行必须是文件的非空非注释的第一个行。

在上面的例子中,所有字段都是标量类型:两个整型(shengao和tizhong),一个string类型(name)。

Repeated 关键字表示重复的那么在go语言中用切片进行代表正如上述文件格式,在消息定义中,每个字段都有唯一的一个标识符。

添加更多消息类型

在一个.proto文件中可以定义多个消息类型。在定义多个相关的消息的时候,这一点特别有用——例如,如果想定义与SearchResponse消息类型对应的回复消息格式的话,你可以将它添加到相同的.proto文件中

syntax = "proto3";

message PandaRequest {
string name = ;
int32 shengao = ;
int32 tizhong = ;
}
message PandaResponse {
...
}

添加注释

向.proto文件添加注释,可以使用C/C++/java/Go风格的双斜杠(//) 语法格式,如:

syntax = "proto3";

message PandaRequest {
string name = ; //姓名
int32 shengao = ; //身高
int32 tizhong = ; //体重
}
message PandaResponse {
...
}

 从.proto文件生成了什么?

当用protocol buffer编译器来运行.proto文件时,编译器将生成所选择语言的代码,这些代码可以操作在.proto文件中定义的消息类型,包括获取、设置字段值,将消息序列化到一个输出流中,以及从一个输入流中解析消息。

对C++来说,编译器会为每个.proto文件生成一个.h文件和一个.cc文件,.proto文件中的每一个消息有一个对应的类。

对Python来说,有点不太一样——Python编译器为.proto文件中的每个消息类型生成一个含有静态描述符的模块,,该模块与一个元类(metaclass)在运行时(runtime)被用来创建所需的Python数据访问类。

对go来说,编译器会为每个消息类型生成了一个.pd.go文件。

标准数据类型

一个标量消息字段可以含有一个如下的类型——该表格展示了定义于.proto文件中的类型,以及与之对应的、在自动生成的访问类中定义的类型:

默认值

当一个消息被解析的时候,如果被编码的信息不包含一个特定的元素,被解析的对象锁对应的域被设置位一个默认值,对于不同类型指定如下:

对于strings,默认是一个空string

对于bytes,默认是一个空的bytes

对于bools,默认是false

对于数值类型,默认是0

使用其他消息类型

你可以将其他消息类型用作字段类型。例如,假设在每一个PersonInfo消息中包含Person消息,此时可以在相同的.proto文件中定义一个Result消息类型,然后在PersonInfo消息中指定一个Person类型的字段

message PersonInfo {
repeated Person info = ;
}
message Person {
string name = ;
int32 shengao = ;
repeated int32 tizhong = ;
}

使用proto2消息类型

在你的proto3消息中导入proto2的消息类型也是可以的,反之亦然,然后proto2枚举不可以直接在proto3的标识符中使用(如果仅仅在proto2消息中使用是可以的)。

嵌套类型

你可以在其他消息类型中定义、使用消息类型,在下面的例子中,Person消息就定义在PersonInfo消息内,如:

message PersonInfo {
message Person {
string name = ;
int32 shengao = ;
repeated int32 tizhong = ;
}
repeated Person info = ;
}

如果你想在它的父消息类型的外部重用这个消息类型,你需要以PersonInfo.Person的形式使用它,如:

message PersonMessage {
PersonInfo.Person info = ;
}

当然,你也可以将消息嵌套任意多层,如:

message Grandpa {     // Level 0
message Father { // Level 1
message son { // Level 2
string name = ;
int32 age = ;
}
}
message Uncle { // Level 1
message Son { // Level 2
string name = ;
int32 age = ;
}
}

定义服务(Service)

如果想要将消息类型用在RPC(远程方法调用)系统中,可以在.proto文件中定义一个RPC服务接口,protocol buffer 编译器将会根据所选择的不同语言生成服务接口代码及存根。如,想要定义一个RPC服务并具有一个方法,该方法能够接收 SearchRequest并返回一个SearchResponse,此时可以在.proto文件中进行如下定义:

service SearchService {
//rpc 服务的函数名 (传入参数)返回(返回参数)
rpc Search (SearchRequest) returns (SearchResponse);
}

Demo:

syntax = "proto2";

package proto.client_type;

import "proto_basic.proto";

option java_package = "com.xxxx.common.proto";
option java_outer_classname = "ClientTypeProto"; message ClientTypeInfo {
optional uint32 client_type_id = ; // 类型ID
optional string client_type_code = ; // 类型标识
optional string client_type_name = ; // 类型名称
optional string create_time = ; // 创建时间
optional string update_time = ; // 更新时间 } //获取终端类型列表参数
message QueryClientTypeListRequest {
optional proto.basic.RequestBasic basic = ;
optional string client_type_code = ; // 类型标识
optional string client_type_name = ; // 类型名称
optional uint32 index = ; // 页码
optional uint32 size = ; // 单页长度
} //返回终端类型列表参数
message QueryClientTypeListResponse {
optional proto.basic.ResponseBasic basic = ;
optional uint32 current_page = ; // 当前页码
optional uint64 total_page = ; // 总页码
optional uint64 total_count = ; // 总个数
repeated ClientTypeInfo client_type_list = ; //活动信息
}

生成proto

protoc --java_out=../java proto_upush_wx_account.proto




Protobuf 完整解析 - 公司最常用的数据交互协议的更多相关文章

  1. 分布式环境中,模块数据交互协议分析 (百度brpc)

    1. 背景 之前听到同事说,要为自己的模块考虑写个数据协议.今天有空想了一下.写出来,方便后续使用. 开源代码brpc中可以支持多种协议,nshead.redis.mongo等20多种协议. 2. 什 ...

  2. JSONP -- 跨域数据交互协议

    一.概念 ①传统Ajax:交互的数据格式——自定义字符串或XML描述: 跨域——通过服务器端代理解决. ②如今最优方案:使用JSON格式来传输数据,使用JSONP来跨域. ③JSON:一种数据交换格式 ...

  3. JSONP(跨域请求) —— 一种非官方跨域数据交互协议

    1.JSONP的作用 由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名.协议.端口)的资源,为 了实现跨域请求,可以通过script标签实现跨域请求,然后再服务器端输出JSON数 ...

  4. web实现数据交互的几种常见方式

    前言 在当今社会,作为一名前端程序猿,并不是一昧的去制作静态页面就可以满足滴:你说你会制作网页,好吧,只能说你算是一个前端程序猿.但这是你作为一个程序猿最基本的能力,并不会为你进行加分: 我们都明白, ...

  5. Django学习笔记(8)——前后台数据交互实战(AJAX)

    这里将自己这段时间学习的关于前后台数据交互的笔记写在这里,这里包含了Django传输数据给JS,AJAX的相关问题,跨域问题,如何解决AJAX的跨域问题等等.比较凌乱,请看到这篇博客的盆友见谅,如果我 ...

  6. WebSocket数据包协议详解

    其实我一直想不明白HTML5包装个应用层办议作为Socket通过基础目的是为了什么,其实直接支持Socket tcp相对来说更加简单灵活.既然标准已经制定而浏览器也支持那对于我们开发者来说只能用的分. ...

  7. C#操作IIS完整解析

    原文:C#操作IIS完整解析 最近在为公司实施做了一个工具,Silverlight部署早已是轻车熟路, 但对于非技术人员来说却很是头疼的一件事,当到现场实施碰到客户情况也各不相同, 急需一个类似系统备 ...

  8. 大数据学习day39----数据仓库02------1. log4j 2. 父子maven工程(子spring项目的创建)3.项目开发(埋点日志预处理-json数据解析、清洗过滤、数据集成实现、uid回补)

    1. log4j(具体见log4j文档) log4j是一个java系统中用于输出日志信息的工具.log4j可以将日志定义成多种级别:ERROR  /  WARN  /  INFO  /  DEBUG ...

  9. mysql交互协议解析——mysql包基础数据、mysql包基本格式

    mysql交互协议是开发mysql周边组件常用的协议,如JDBC,libmysql等等. 在此我们要认识到mysql交互协议其实是半双工的交互协议,至于为什么,这里就先挖个小坑,以后再填. 在探讨my ...

随机推荐

  1. LR 两种录制:html与url

    一直在使用LR,对于Html_based script和Url-based script 两种录制方式之间,要如何选择,仍是一知半解.最近测试时遇到同样的业务功能,两种录制方式的脚本,单次执行时间差别 ...

  2. [Windows Server 2012] 安装IIS8.5及FTP

    ★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com ★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频. ★ 本节我们将带领大家:安装IIS ...

  3. android studio更新后,构建gradle卡在Refreshing Gradle Project 解决办法

    Android Studio每次更新版本都会更新Gradle这个插件,但由于墙的问题,导致更新很慢或者最后更新失败,又是停止在Refreshing Gradle Project ,有时新建项目的时候报 ...

  4. 禁用DRM

    10G: alter system set "_gc_policy_time"=0 scope=spfile sid='*'; alter system set "_gc ...

  5. Smart Contracts

    A smart contract is a computer code running on top of a blockchain containing a set of rules under w ...

  6. nginx 安全配置文档

    1.配置文档中有多处明确写出了nginx的配置文件路径,该路径是测试环境中的路径,线上系统的nginx配置文件与文档中所写的路径可能不一样,在进行相关配置时,应以线上配置文件的实际路径为准. 线上系统 ...

  7. axure使用经验

    泛化不常用======伸展也是拉动原件收缩也是拉动原件====== 动态模板相互影响(有的时候会出现这个问题,只需要设置两者的高度,不让两者有包含关系(一点点可以有):====== 实现高级菜单栏(同 ...

  8. 记忆化搜索 || POJ 1088 滑雪

    从任意一点可以往上下左右比它小的数那里走,问最远长度是多少 *解法:每一点dfs搜索一遍 记忆化搜索:http://blog.csdn.net/acmer_sly/article/details/53 ...

  9. QT5:总结篇 控件集合

    一.Layouts 二.Spacers 三.Buttons 四.Item Views(Model-Based) 五.Item Widgets(Item-Based) 六.Containers 七.In ...

  10. react随笔-1(为什么在react使用jq无法正确渲染组件位置)

    今天心血来潮,打开了sublime想玩玩react,然后大家都知道的先引入一大串 就是在百度静态资源库里找到的. 然后贴html代码 对的,没错,就这么一行,毕竟只是测试嘛 然后js代码 大家一定要注 ...