PHP7中Protobuf的安装使用

写这篇文章的缘由是最近在关注RPC框架序列化的一些原理。但是在安装Protobuf的时候,发现网上的教程都太老了,加上目前Protobuf官方已经支持PHP了,不再需要使用第三方插件了。

关于序列化和反序列化

在PRC框架中,数据的传输发生在客户端和服务端,而我们知道基于TCP协议最终传输的是二进制的0/1序列。所以,基于TCP传输协议的RPC服务自然也需要将数据结构转换成二进制,和二进制转换成数据结构的功能。所以,原则上,基于网络的数据传输只能传输二进制表示的字符串

序列化:将数据结构或对象转换成二进制串的过程
反序列化:将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程

但是,传输的二进制序列是完全没有意义的,除非有一套解析二进制串的协议。没错,这个协议可以就是目前我们大家熟知的xml,json协议。当然。除了这两者,还有其他的的序列化和反序列化协议。

几种常见的序列化和反序列协议

XML

XML是一种常用的序列化和反序列化协议,具有跨机器,跨语言等优点。XML历史悠久,其1.0版本早在1998年就形成标准,并被广泛使用至今。XML的格式如下

<note>
<to>George</to>
<from>John</from>
<msg>Don't forget the meeting!</msg>
</note>

可以看出这种序列化协议的优点是可读性和易调试行。但是这种协议的缺点也很明显:额外空间开销大,序列化之后的数据量剧增。

JSON

JSON是一种轻量级的数据交换格式。采用完全独立于编程语言的文本格式来存储和表示数据。如果你跟浏览器Web应用打交道的话,那么JSON一定是应用最广泛的,它的数据格式如下

{
"to":"George",
"from":"John",
"msg":"Don't forget the meeting!"
}

这种序列化协议有很大的优势:

  1. 这样表示非常符合工程师对对象的理解,尤其是js工程师
  2. 和xml一样,可读性强
  3. 和xml相比,更加节省空间,解析速度更快

由于天生的Web友好型,JSON自然而然成了AJAX数据传输的标准协议。JSON目前的使用非常广泛,但是,如果数据传输和响应时间有跟苛刻的要求,那么JSON可能性能还是差点。

Protobuf

Google Protocol Buffer( 简称 Protobuf) 是一种更轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC数据交换格式。数据结构定义文件的格式如下:

syntax = "proto3";
package config;
message MailConfig{
string to = 1;
string from = 2;
string msg = 3;
}

然后这个协议文件客户端和服务端都需要用到。这样,网络发送字节就不需要发送和数据无关的字节了。针对上面的数据结构,序列化成json的长度是63,而按照Protobuf协议序列化之后的长度是41。如果数据更多,效果更明显。

Thrift

和Protobuf类似,但是Protobuf只做数据序列化的工作,而Thrift是一套完整的RPC框架解决方案。由于Thrift的序列化被嵌入到Thrift框架里面,Thrift框架本身并没有透出序列化和反序列化接口,所以如果你使用Thrift框架,那么其实就使用了Thrift的序列化协议。

Thrift是一套完整的RPC解决方案,里面的协议也是一种基于二进制串的序列化协议,如果想要了解更多,这篇文章写得比较好:https://www.ibm.com/developerworks/cn/java/j-lo-apachethrift/

Protobuf的安装使用

json和xml相信大家都比较熟悉,但是在RPC框架中很少使用这两种协议。由于Thrift是一套RPC解决方案,太过庞大,所以我们分析专门解决序列化问题的Protobuf。由于笔者使用的是PHP,所以自然而然使用的是PHP版本的Protobuf。PHP有两种安装模式,第一是composer安装php包的形式,第二种是安装PHP扩展的形式。

PHP和protoc的安装

要安装PHP版本的Protobuf,首先你得有PHP,所以首先安装PHP,笔者使用的PHP7,还需要一个工具protoc,你可以先不用管这个工具是干嘛的,先安装。

工具包 版本 下载地址
PHP 7.1.8 http://php.net/get/php-7.1.8.tar.gz/from/a/mirror
proto 3.0.0 https://github.com/google/protobuf/releases/download/v3.3.0/protobuf-php-3.3.0.zip

最后,笔者安装的PHP版本

[xxx@controller app]$ /usr/bin/php -v
PHP 7.1.8 (cli) (built: Aug 16 2017 03:10:49) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies

笔者安装的protoc版本(注意,有可能安装路径不同)

[xxxx@controller app]$ /usr/local/bin/protoc --version
libprotoc 3.3.0

Protobuf的安装

Protobuf的安装我们采用Composer形式进行安装。如果你还没有安装composer工具,运行下面的命令进行安装:

curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer

查看我们安装的composer版本:

[xxxx@controller app]$ /usr/local/bin/composer --version
Composer version 1.5.1 2017-08-09 16:07:22

准备工作结束。接下来,正式安装Protobuf。

我们首先新建一个文件夹app。然后在app文件夹内新建composer.json文件,文件内容如下:

{
"require":{
"google/protobuf": "^3.3"
}
}

保存之后,在app文件夹下执行composer install安装命令

[xxxx@controller app]$ /usr/local/bin/composer install
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
- Installing google/protobuf (v3.4.0): Downloading (100%)

安装完成之后,如果你看到的app文件夹包含下面文件,表示安装成功

[xxxx@controller app]$ ls
composer.json composer.lock vendor

Protobuf的简单例子

上面的步骤安装完之后,我们来看一下一个简单的例子,这个例子很简单,一个角色是Writer,一个角色是Reader。Writer向磁盘中写二进制字符串,Reader要读取二进制字符串中的信息。

书写 .proto 文件

我们知道,二进制序列如果没有协议,根本不知道它表示的是什么,首先我们需要编写一个 proto 文件,定义我们程序中需要处理的结构化数据,在 protobuf的术语中,结构化数据被称为 Message。我们这里定义一个mail的proto文件mail.proto,这个文件还是放在我们的app目录下, 文件内容如下:

syntax = "proto3";
package mail;
message MailConfig{
string to = 1;
string from = 2;
string msg = 3;
}

其中,syntax表示我们使用的是proto3语法规则。packge的名字叫做mail,然后定义了一个名字为MailConfig的消息。这个消息有3个成员,string类型的to,string类型的from,string类型的msg。

编译 .proto 文件

还记得我们下载安装的protoc工具吗,这个玩意就是拿来编译.proto文件的,它可以将.proto文件编译成很多种目标语言,java,python,php等。这里我们需要使用这个工具,将.proto文件生成目标PHP语言。

/usr/local/bin/protoc --php_out=. mail.proto

--php-out表示生成目标语言存放位置,我们就放在当前目录下,也就是app文件夹下。如果生成目标语言成功,那么app文件夹下的目录如下:

[xxxx@controller app]# ls
composer.json composer.lock GPBMetadata Mail mail.proto vendor

编写测试

在app中编写test.php,文件内容如下:

<?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);

最终程序的输出:

[xxxx@controller app]# php test.php
array(3) {
["to"]=>
string(6) "George"
["from"]=>
string(4) "John"
["msg"]=>
string(25) "Don't forget the meeting!"
}

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

后续

到这里,肯定有人觉得效率还是不够高,那么没关系,protobuf有C语言扩展版的实现,如果你对效率有极致的要求,那么强烈建议使用C语言扩展版的protobuf。可以参考官方安装方式:https://github.com/google/protobuf/tree/master/php

PHP7中Protobuf的安装使用的更多相关文章

  1. Protobuf从安装到配置整理帖

    新做的Mini项目计划使用Google的Protobuf来做,关于Protobuf是什么玩意能干什么请自己去看这里:http://code.google.com/p/protobuf/ 这里讲一下安装 ...

  2. Protobuf从安装到配置整理帖 --转

    新做的Mini项目计划使用Google的Protobuf来做,关于Protobuf是什么玩意能干什么请自己去看这里:http://code.google.com/p/protobuf/ 这里讲一下安装 ...

  3. php7源码编译安装

    以下以CentOS 7.2为例,安装php的运行环境,首先打开php官网http://php.net/点击导航栏的Downloads进入下载页面:http://php.net/downloads.ph ...

  4. 什么是PHP7中的孤儿进程与僵尸进程

    什么是PHP7中的孤儿进程与僵尸进程 基本概念 我们知道在unix/linux中,正常情况下,子进程是通过父进程创建的,子进程在创建新的进程.子进程的结束和父进程的运行是一个异步过程,即父进程永远无法 ...

  5. 苹果mac电脑中brew的安装使用及卸载详细教程

    brew 又叫Homebrew,是Mac OSX上的软件包管理工具,能在Mac中方便的安装软件或者卸载软件, 只需要一个命令, 非常方便 brew类似ubuntu系统下的apt-get的功能 安装br ...

  6. mac中使用brew安装软件,下载太慢怎么办?

    mac中使用brew安装软件,下载太慢怎么办? 本文所说的软件是指较大的软件,如果软件较小,例如软件只有几M,那么使用此方法后,提升会非常小. 了解brew原理: 1: 从网络下载安装包 2: 执行一 ...

  7. CentOs中mysql的安装与配置

    在linux中安装数据库首选MySQL,Mysql数据库的第一个版本就是发行在Linux系统上,其他选择还可以有postgreSQL,oracle等 在Linux上安装mysql数据库,我们可以去其官 ...

  8. 腾讯云Linux系统中启动自己安装的tomcat

    腾讯云Linux系统中启动自己安装的tomcat 首先通过工具查看一下安装的tomcat的位置 进入命令行之后输入以下指令: 此时,tomcat已经启动了.

  9. Ubuntu 中软件的安装、卸载以及查看的方法总结

    Ubuntu 中软件的安装.卸载以及查看的方法总结 博客分类: Linux UbuntuDebian配置管理CacheF#  说明:由于图形化界面方法(如Add/Remove... 和Synaptic ...

随机推荐

  1. CV2图像操作

    一.读入图像使用函数cv2.imread(filepath,flags)读入一副图片filepath:要读入图片的完整路径flags:读入图片的标志 cv2.IMREAD_COLOR:默认参数,读入一 ...

  2. 封装 oschina.net 表情选择

    1. [代码]jquery.facial.js //从OSCHINA.NET 提取出来的 表情选择 插件 by zhouxiang //如果有不满足的地方 可以自己改改 没事随便写写的 style 和 ...

  3. window.onload 添加多个函数绑定

    window.onload = function(){alert(2)} function addEvent (fun) { var old = window.onload; if(typeof ol ...

  4. 一個在WCF學習中的小教訓(本人非科班菜鳥,此經驗無參考價值,衹是自己的經驗記錄)

    1.关于“ServiceHost 仅支持类服务类型”的解决:   Service属性必须执行,不是接口. 改为下图所示: 解决! (注:按朱哥的方法WCF已经可以通信---截至今天的11:11(例子在 ...

  5. php获取客户端IP地址的几种方法(转)

    [php] view plain copy php获取客户端IP地址的几种方法 方法一 <?php $iipp=$_SERVER["REMOTE_ADDR"]; echo $ ...

  6. HIVE SQL JOIN

    最近总结了一下hive表关联的用法,与Postgres表关联还是有细微差别,总结在这里方便以后查看. join语法 join_table: table_reference [INNER] JOIN t ...

  7. cudnn 卷积例子

    运行环境:linux cuda cudnn cudnn API:https://docs.nvidia.com/deeplearning/sdk/cudnn-developer-guide/index ...

  8. C++ STL源码剖析

    stl_config.h defalloc.h stl_alloc.h memory.cpp stl_construct.h stl_uninitialized.h stl_iterator.h ty ...

  9. HNOI2008玩具装箱 斜率优化

    题目描述 P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具, ...

  10. bzoj 3572: [Hnoi2014]世界树 虚树

    题目: Description 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森,在他们的信条里,公平是使世界树能够生生 ...