PHP7 使用 protobuf,以及protobuf简介

场景:公司需要上传一些数据到别的平台,需要用到protobuf 数据结构的文件

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 = 2;
   string msg = 3;
}

然后这个协议文件客户端和服务端都需要用到。这样,网络发送字节就不需要发送和数据无关的字节了。针对上面的数据结构,序列化成json的长度是63,而按照Protobuf协议序列化之后的长度是41。如果数据更多,效果更明显。
PHP如果要使用protobuf 需要安装 proto + 安装protobuf composer包
  • proto 用于根据protobuf数据结构文件(.proto)生成对应的类,用于生成protobuf文件
  • 安装 google/protobuf composer 包composer require google/protobuf
proto下载地址
工具包版本下载地址
proto3.0.0https://github.com/google/protobuf/releases/download/v3.3.0/protobuf-php-3.3.0.zip

使用案例:

  1. 我们首先新建一个文件夹app。然后在app文件夹内新建composer.json文件,文件内容如下:
{
   "require":{
       "google/protobuf": "^3.3"
   }
}
  1. 保存之后,在app文件夹下执行composer install安装命令

3 书写 .proto 文件
我们知道,二进制序列如果没有协议,根本不知道它表示的是什么,首先我们需要编写一个 proto 文件,定义我们程序中需要处理的结构化数据,在 protobuf的术语中,结构化数据被称为 Message。我们这里定义一个mail的proto文件mail.proto,这个文件还是放在我们的app目录下, 文件内容如下:
其中,syntax表示我们使用的是proto3语法规则。packge的名字叫做mail,然后定义了一个名字为MailConfig的消息。这个消息有3个成员,string类型的to,string类型的from,string类型的msg。

syntax = "proto3";
package mail;
message MailConfig{
   string to = 1;
   string from = 2;
   string msg = 3;
}
  1. 编译 .proto 文件,这里我们需要使用protoc,将.proto文件生成目标PHP语言。–php-out表示生成目标语言存放位置,我们就放在当前目录下,也就是app文件夹下
protoc --php_out=. mail.proto
  1. 编写测试
<?php
    require_once('vendor/autoload.php');
    require_once('GPBMetadata/Mail.php');
    require_once('Mail/MailConfig.php');
    /**
    * Writer写数据,Protobuf抽象成调用相关set函数即可
    */
    $foo = new \Mail\MailConfig();  
    $foo->setTo("George");  
    $foo->setFrom("John");  
    $foo->setMsg("Don't forget the meeting!");  
    $packed = $foo->serializeToString();//这里你也可以选择serializeToJsonString序列化成JSON  
    //Reader读数据,Protobuf抽象成调用相关get函数即可
    $res = new \Mail\MailConfig();
    $res->mergeFromString($packed);  
    $jsonArr = [
        "to"=> $res->getTo(),
        "from"=> $res->getFrom(),
        "msg"=> $res->getMsg(),
    ];
    var_dump($jsonArr);

输出:

array(3) {
  ["to"]=>
  string(6) "George"
  ["from"]=>
  string(4) "John"
  ["msg"]=>
  string(25) "Don't forget the meeting!"
}

这就是一个典型的序列化和反序列化的例子,试想一下,如果我们将序列化好的二进制串通过网络发送到另一端,而另一端再使用同样的.proto文件生成的目标语言解析。这将变得比json更加的高效。因为我们可以传输更少的字节,反序列化速度也非常快。

如果使用composer包效率比较低,可以使用protobuf 的PHP C扩展,安装方法如下:
git clone https://github.com/allegro/php-protobuf
cd php-protobuf/
phpize
./configure
make && make install

//然后在php.ini里面加一下extension = "protobuf.so",再重启php-fpm

protoc --php_out=./ jrttDmp.proto

附录:

  1. 一看就懂系列之 protobuf的php版的教程https://blog.csdn.net/u011957758/article/details/52455231
  2. PHP protobuf 扩展 https://github.com/allegro/php-protobuf
  3. Google protobuf 所有语言扩展 https://github.com/protocolbuffers/protobuf
  4. protobuf3 使用 https://www.jianshu.com/p/d2bdc966086b
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值