protobuf 是做什么的
专业的解答:
Protocol Buffers 是一种轻便高效的结构化数据存储格式,可用于结构化数据串行化,很适合做数据存储或 RPC 数据交换格式。它可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。简单的说就是干和xml一样的事,把某种数据结构的信息,以某种格式保存起来。主要用于数据存储、传输协议格式等场合
了解了下这种数据格式使用的场景。
1、RPC序列化,转自:http://blog.leanote.com/post/weibo-007/f40e8fee0dfb
在PRC框架中,数据的传输发生在客户端和服务端,而我们知道基于TCP协议最终传输的是二进制的0/1序列。所以,基于TCP传输协议的RPC服务自然也需要将数据结构转换成二进制,和二进制转换成数据结构的功能。所以,原则上,基于网络的数据传输只能传输二进制表示的字符串
但是,传输的二进制序列是完全没有意义的,除非有一套解析二进制串的协议。没错,这个协议可以就是目前我们大家熟知的xml,json协议。当然。除了这两者,还有其他的的序列化和反序列化协议。
XMl
<note>
<to>George</to>
<from>John</from>
<msg>Don't forget the meeting!</msg>
</note>
可以看出这种序列化协议的优点是可读性和易调试行。但是这种协议的缺点也很明显:额外空间开销大,序列化之后的数据量剧增。
JSON
{
"to":"George",
"from":"John",
"msg":"Don't forget the meeting!"
}
这种序列化协议有很大的优势:
1. 这样表示非常符合工程师对对象的理解,尤其是js工程师
2. 和xml一样,可读性强
3. 和xml相比,更加节省空间,解析速度更快
4. 由于天生的Web友好型,JSON自然而然成了AJAX数据传输的标准协议。JSON目前的使用非常广泛,但是,如果数据传输和响应时间有跟苛刻的要求,那么JSON可能性能还是差点。
Protobuf (Google Protocol Buffer)数据结构定义文件的格式如下:
syntax = "proto3";
package config;
message MailConfig{
string to = 1;
string from
Google Protocol Buffers 简称 Protobuf,类似 json 或 XML,是一种序列化结构数据的机制,但是比它们更小、更快、更简单。同时支持多语言,跨平台。
目前主要有两个大版本:proto2 和 proto3。
其中 proto2 支持 Java、Python、 Objective-C、和 C++
。
proto3 增加了对Go、JavaNano、Ruby、和 C#
的支持。
syntax = "proto3"; package tutorial; import "google/protobuf/timestamp.proto"; option java_package = "com.katyusha.aron.demo"; option java_outer_classname = "AddressBookProtos"; message Person { string name = 1; int32 id = 2; string email = 3; enum PhoneType{ MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { string number = 1; PhoneType type = 2; } repeated PhoneNumber phone = 4; } message AddressBook { repeated Person person = 1; }
Protobuf使用.proto
文件来定义数据格式,并同时提供编译器将这些文件编译为各种语言的源码。
message 格式非常简单。每种类型的 message 包含一个或者多个唯一编码字段,每个字段由名称和值类型组成,值类型可以是数字(整形或者浮点型)、布尔值、字符串、原始字节,甚至是其他的 message(如上例所示)。Protobuf 允许 message 中包含 message,以达到分层嵌套。
值得注意的一点是,每个属性都有唯一的一个tag
,上面的0,1,2...
等,这些tag
非常重要,是 Prodobuf 编码时
Protobuf是一种平台无关、语言无关、可扩展且轻便高效的序列化数据结构的协议,可以用于网络通信和数据存储。
protoc -I=$SRC_DIR --java_out=$DST_DIR $SRC_DIR/addressbook.proto
-I 编译源文件的目录
--java_out 编译目录文件
通过这个命令会自动编译出java代码,目前protobuf支持以下语言
Language | Source |
---|---|
C++ | src |
Java | java |
Python | python |
Objective-C | objectivec |
C# | csharp |
JavaNano | javanano |
JavaScript | js |
Ruby | ruby |
Go | golang/protobuf |
PHP | php |
Dart | dart-lang/protobuf |
由于命令行的方式编译代码非常繁琐,且效率极低。谷歌提供了开源的Protobuf Gradle插件
简单说一下配置方式
在project.gradle中配置
buildscript { repositories { mavenLocal() } dependencies { classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.6-SNAPSHOT' } }
在modle.gradle中配置
apply plugin: 'com.google.protobuf' dependencies { // You need to depend on the lite runtime library, not protobuf-java compile 'com.google.protobuf:protobuf-lite:3.0.0' } protobuf { protoc { // You still need protoc like in the non-Android case artifact = 'com.google.protobuf:protoc:3.0.0' } plugins { javalite { // The codegen for lite comes a
git clone https://github.com/protocolbuffers/protobuf.git
./autogen.sh ./configure --prefix=/usr/local/protobuf make sudo make install
cd protobuf/php/ext/google/protobuf /usr/local/php-7.1.11/bin/phpize ./configure --with-php-config=/usr/local/php-7.1.11/bin/php-config make sudo make install
添加配置:
/usr/local/php-7.1.11/bin/php --ini | grep php.ini sudo vim /usr/local/php-7.1.11/etc/php.ini extension=protobuf.so
编写proto 协议文件
vim User.proto syntax="proto3"; message UserInfo { int32 id = 1; string name = 2; }
用protoc编译协议文件,会在当前目录下生成GPBMetadata目录和UserInfo.php文件
/usr/local/protobuf/bin/protoc --php_out=./ User.proto
安装php库:
composer require google/protobuf
编写php脚本
<?php require('./vendor/autoload.php'); require('./UserInfo.php'); require('./GPBMetadata/User.php'); $pbUserInfo = new UserInfo(); $pbUserInfo->setId(1001); $pbUserInfo->setName('jack'); $str = $pbUserInfo->serializeToString(); $ptTempUser = new UserInfo(); $ptTempUser->mergeFromString($str); var_dump("id:".$