PHP7中Protobuf的安裝使用php
寫這篇文章的原因是最近在關注RPC框架序列化的一些原理。可是在安裝Protobuf的時候,發現網上的教程都太老了,加上目前Protobuf官方已經支持PHP了,再也不須要使用第三方插件了。java
在PRC框架中,數據的傳輸發生在客戶端和服務端,而咱們知道基於TCP協議最終傳輸的是二進制的0/1序列。因此,基於TCP傳輸協議的RPC服務天然也須要將數據結構轉換成二進制,和二進制轉換成數據結構的功能。因此,原則上,基於網絡的數據傳輸只能傳輸二進制表示的字符串python
序列化:將數據結構或對象轉換成二進制串的過程
反序列化:將在序列化過程當中所生成的二進制串轉換成數據結構或者對象的過程
可是,傳輸的二進制序列是徹底沒有意義的,除非有一套解析二進制串的協議。沒錯,這個協議能夠就是目前咱們你們熟知的xml,json協議。固然。除了這二者,還有其餘的的序列化和反序列化協議。git
XML是一種經常使用的序列化和反序列化協議,具備跨機器,跨語言等優勢。XML歷史悠久,其1.0版本早在1998年就造成標準,並被普遍使用至今。XML的格式以下github
<note>
<to>George</to>
<from>John</from>
<msg>Don't forget the meeting!</msg>
</note>
能夠看出這種序列化協議的優勢是可讀性和易調試行。可是這種協議的缺點也很明顯:額外空間開銷大,序列化以後的數據量劇增。apache
JSON是一種輕量級的數據交換格式。採用徹底獨立於編程語言的文本格式來存儲和表示數據。若是你跟瀏覽器Web應用打交道的話,那麼JSON必定是應用最普遍的,它的數據格式以下編程
{
"to":"George",
"from":"John",
"msg":"Don't forget the meeting!"
}
這種序列化協議有很大的優點:
1. 這樣表示很是符合工程師對對象的理解,尤爲是js工程師
2. 和xml同樣,可讀性強
3. 和xml相比,更加節省空間,解析速度更快json
因爲天生的Web友好型,JSON天然而然成了AJAX數據傳輸的標準協議。JSON目前的使用很是普遍,可是,若是數據傳輸和響應時間有跟苛刻的要求,那麼JSON可能性能仍是差點。ubuntu
Google Protocol Buffer( 簡稱 Protobuf) 是一種更輕便高效的結構化數據存儲格式,能夠用於結構化數據串行化,或者說序列化。它很適合作數據存儲或 RPC數據交換格式。數據結構定義文件的格式以下:瀏覽器
syntax = "proto3";
package config;
message MailConfig{
string to = 1;
string from = 2;
string msg = 3;
}
而後這個協議文件客戶端和服務端都須要用到。這樣,網絡發送字節就不須要發送和數據無關的字節了。針對上面的數據結構,序列化成json的長度是63,而按照Protobuf協議序列化以後的長度是41。若是數據更多,效果更明顯。
和Protobuf相似,可是Protobuf只作數據序列化的工做,而Thrift是一套完整的RPC框架解決方案。因爲Thrift的序列化被嵌入到Thrift框架裏面,Thrift框架自己並無透出序列化和反序列化接口,因此若是你使用Thrift框架,那麼其實就使用了Thrift的序列化協議。
Thrift是一套完整的RPC解決方案,裏面的協議也是一種基於二進制串的序列化協議,若是想要了解更多,這篇文章寫得比較好:https://www.ibm.com/developerworks/cn/java/j-lo-apachethrift/
json和xml相信你們都比較熟悉,可是在RPC框架中不多使用這兩種協議。因爲Thrift是一套RPC解決方案,太過龐大,因此咱們分析專門解決序列化問題的Protobuf。因爲筆者使用的是PHP,因此天然而然使用的是PHP版本的Protobuf。PHP有兩種安裝模式,第一是composer安裝php包的形式,第二種是安裝PHP擴展的形式。
要安裝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的安裝咱們採用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
上面的步驟安裝完以後,咱們來看一下一個簡單的例子,這個例子很簡單,一個角色是Writer,一個角色是Reader。Writer向磁盤中寫二進制字符串,Reader要讀取二進制字符串中的信息。
咱們知道,二進制序列若是沒有協議,根本不知道它表示的是什麼,首先咱們須要編寫一個 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。
還記得咱們下載安裝的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
參考安裝:http://blog.leanote.com/post/weibo-007/f40e8fee0dfb
http://www.hello1010.com/php-protobuf