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. linux 系统监控好文

    摘自: http://os.51cto.com/art/201005/200714_all.htm

  2. 也来谈幂等和CAS

    什么是幂等? 一个方法,不管你执行多少次,保证执行的结果总是相同的.这种方法或者服务就是幂等的. 什么是CAS? CAS是Compare And Set的缩写,顾名思义,就是先比较再设置,这种方式避免 ...

  3. jsoup抓取网页内容

    java项目有时候我们需要别人网页上的数据,怎么办?我们可以借助第三方架包jsou来实现,jsoup的中文文档,那怎么具体的实现呢?那就跟我一步一步来吧 最先肯定是要准备好这个第三方架包啦,下载地址, ...

  4. 机器学习(十四)— kMeans算法

    参考文献:https://www.jianshu.com/p/5314834f9f8e # -*- coding: utf-8 -*- """ Created on Mo ...

  5. Java_io_02_从一个目录拷贝文件到另一个目录下

    java从一个目录拷贝文件到另一个目录下   http://www.cnblogs.com/langtianya/p/4857524.html ** * 复制单个文件 * @param oldPath ...

  6. JavaUtil_02_二维码的生成与解析

    1.引入jar包 zxing-core-1.7.jar  :   http://viralpatel.net/blogs/download/jar/zxing-core-1.7.jar zxing-j ...

  7. 基于zepto使用swipe.js制作轮播图demo

    在移动web开发中,由于手机界面较小,为了能展示更多的图片经常使用轮播图并且还需要考虑到手机流量的问题,通过请教他人以及百度,个人感觉swipe.js比较好用 它是一个纯javascript工具,不需 ...

  8. codeforces 707A A. Brain's Photos(水题)

    题目链接: A. Brain's Photos 题意: 问是黑白还是彩色; 思路: 没有思路: AC代码: #include <iostream> #include <cstdio& ...

  9. the referenced script on this behaviour is missing!

    1.看看你脚本上挂的某个组件是不是发生了变动,比如被删除了什么的 2.最有可能的是你创建完脚本后,中途改过脚本的名字,致使脚本名字和内部的名字不统一.

  10. ACM学习历程—HDU5422 Rikka with Graph(贪心)

    Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situation, so he ...