GoogleProtobuf入门

发表:2018-01-04 13:32:52

一、GooGlePrototbuf是什么?

Protocol Buffers 是一种轻便高效的结构化数据存储格式,可用于结构化数据串行化,很适合做数据存储或 RPC 数据交换格式。它可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。

简单的说就是干和xml一样的事,把某种数据结构的信息,以某种格式保存起来。主要用于数据存储、传输协议格式等场合。

那和常见的XML有什么区别?

1.时间维度:xml格式化(序列化)的开销倒还好;但是XML解析(反序列化)的开销就呵呵了。
2.空间维度:XML格式为了有较好的可读性,引入了一些冗余的文本信息,所以空间开销也不是太好。


二、protobuf有什么好处?


1.对于数据结构的序列化反序列化等性能均优于xml
2.代码生成机制,使用起来十分方便(后续会提到)
3.明星项目有使用:据了解 google、新浪、美拍等均有使用protobuf,所以搬到项目使用肯定不会错。



三、protobuf的安装过程


准备资源:
protobuf-2.6.1安装包
php的protobuf扩展包


1)安装

wget https://github.com/google/protobuf/releases/download/v2.6.1/protobuf-2.6.1.tar.gz
tar zxvf protobuf-2.6.1.tar.gz
cd protobuf-2.6.1/
./configure --prefix=/usr/local/protobuf
make && make install
export PATH=/usr/local/protobuf/bin:$PATH
protoc --version


注意此处的包不能乱下载网上现成的。必须要大于2.5版本的。原因:最新版的protobuf代码生成机制要求必须大于2.5版本


2)安装php的protobuf扩展

wget https://github.com/allegro/php-protobuf/archive/master.zip
unzip master.zip
cd php-protobuf-master
yum install php-devel(安装依赖)
phpize
./configure --with-php-config=/usr/local/php/bin/php-config
make && make install
//然后在php.ini里面加一下extension = "protobuf.so",再重启php与nginx即可。



3)安装composer

cd /path/to/you/../php-protobuf-master (存放php-protobuf-master的文件夹)
curl -s http://getcomposer.org/installer | php
php composer.phar install



四、使用googleprotobuf


1)代码生成机制:生成proto文件

vim cbstest.proto

message Person {
    required string name = 1;
    required int32 id = 2;
    optional string email = 3;
    optional double money = 4;
}



然后执行

php ./php-protobuf-master/protoc-gen-php.php cbstest.proto

然后就会形成一个 Person.php 的文件。

<?php
/**
 * Auto generated from test.proto at 2016-09-06 21:37:46
 */
namespace {
/**
 * Person message
 */
class Person extends ProtobufMessage
{
    /* Field index constants */
    const NAME = 1;
    const ID = 2;
    const EMAIL = 3;
    const MONEY = 4;
    /* @var array Field descriptors */
    protected static $fields = array(
        self::NAME => array(
            'name' => 'name',
            'required' => true,
            'type' => ProtobufMessage::PB_TYPE_STRING,
        ),
...省略...
}


这里会继承ProtobufMessage类,它是在protobuf.so中自动加载的



五、PHP客户端的使用


$foo = new Person();
$foo->setName('hellojammy');
$foo->setId(2);
$foo->setEmail('helloxxx@foxmail.com');
$foo->setMoney(1988894.995);
$packed = $foo->serializeToString();



以上packed就是序列化后的结果,可直接存于数据库中。

$p = new Person();
$p->parseFromString($packed);
echo $p->getName() ."n";
echo $p->getEmail() ."n";
echo $p->getMoney() ."n";
echo $p->getId() . "n";


以上用于数据的反序列化。


封装一下代码。

public function encode($data){
    $fields = $this->fields();
    foreach ($fields as $key => $_item) {
        $field_name = $_item['name'];
        if(isset($data[$field_name])) {
            $this->set($key, $data[$field_name]);
        }
    }
    try {
        $packed = $this->serializeToString();
    } catch (Exception $ex) {
        $data['fields'] = $fields;
        $data['error']  = $ex->getMessage();
        writeLog($data, 'encode_new_pb_failed');
        $packed = '';
    }
    return $packed;
}
public function decode($packed){
    try {
        $this->parseFromString($packed);
    } catch (Exception $ex) {
        writeLog($ex->getMessage(), 'decode_new_pb_failed');
    }
    $data = array();
    $fields = $this->fields();
    foreach ($fields as $key => $_item) {
        $field_name = $_item['name'];
        $data[$field_name] = $this->get($key);
    }
    return $data;
}


参考资源:


https://www.jianshu.com/p/563e171b7dc9

https://www.ibm.com/developerworks/cn/linux/l-cn-gpb/index.html

附录:

protobuf的githab
protobuf的版本资源






相关文章