使用Redis+php-resque實現訊息佇列
一、Redis安裝
1. 獲取原始碼
shell># cd /usr/local/src
shell># wget http://download.redis.io/releases/redis-2.6.16.tar.gz
shell># tar -zxvf redis-2.6.16.tar.gz
shell># cd redis-2.6.16
2. 編譯、安裝
shell># make
3. 配置Redis
編輯redis.conf檔案
shell># vi /usr/local/src/redis-2.6.16/redis.conf
daemonize = yes
4. 啟動Redis
shell># src/redis-server /usr/local/src/redis-2.6.16/redis.conf
5. 測試連線
shell># src/redis-cli
redis> set foo bar
OK
redis> get foo
“bar”
redis> exit;
二、phpredis 安裝
1. 獲取原始碼
shell># cd /usr/local/src
shell># wget https://github.com/nicolasff/phpredis/archive/2.2.3.tar.gz -O nicolasff-phpredis-2.2.3.tar.gz
shell># tar -zxvf nicolasff-phpredis-2.2.3.tar.gz
shell># cd phpredis-2.2.3
2. 編譯、安裝
shell># /usr/local/php/bin/phpize
shell># ./configure –-with-php-config=/usr/local/php/bin/php-config
shell># make && make install
3. 配置php.ini
shell># vi /usr/local/php/etc/php.ini
extension=redis.so
4. 重啟nginx & php-fpm
三、php-resque安裝
*準備工作
需要pcntl支援
安裝git
shell># yum -y install git
安裝Composer
shell># cd /usr/local/bin
shell># curl –sS https://getcomposer.org/installer | php
shell># mv composer.phpar /usr/local/bin/composer
修改 php.ini
disable_functions = … …
將proc_open和proc_get_status以及exec刪除
儲存後,重啟LNMP
1. 獲取原始碼
shell># cd /home/wwwroot/default
shell># git clone git://github.com/chrisboulton/php-resque.git
2. 安裝
shell># cd php-resque
shell># composer install
四、Demo
1. 一個Job
Job|任務:一個Job就是一個需要在後臺完成的任務,比如郵件傳送,就可以抽象為一個Job。在Resque中一個Job就是一個Class。
shell># cd php-resque
shell># vim demo/job.php
class PHP_Job
{
public function perform()
{
fwrite(STDOUT, 'Start job! -> ‘);
sleep(10);
fwrite(STDOUT, ‘Job ended!’ . PHP_EOL);
}
}
這個Job的具體任務:輸出’Start job! ->’,然後等待10秒鐘後,再次輸出’Job ended!’。
在Resque的設計中,一個Job必須存在一個perform方法,Worker則會自動執行這個方法。
2. 將Job插入佇列
Queue|佇列:就是標題中的訊息佇列。在Resque中,佇列由Redis來負責實現。Resque還提供了一個簡單的佇列管理器,可以實現將Job插入/取出佇列等功能。
shell># vim demo/queue.php
if(empty($argv[1]) or empty($argv[2])) {
die('Specify the name of a queue or job to add. e.g, php queue.php default PHP_Job');
//在cli命令列中執行queue.php 後面必須加上兩個引數,第一個引數為queue的名稱 第二個引數為job的名稱,必須同之前編寫的Job類的類名。
}
require __DIR__ . '/init.php';
date_default_timezone_set('GMT');
Resque::setBackend('127.0.0.1:6379');
$args = array(
'time' => time(),
‘array’ => array(
‘test’ => ‘test’,
),
);
$jobId = Resque::enqueue($argv[1], $argv[2], $args, true);
echo “Queued job “.$jobId.”\n\n”;
在cli方式中執行:
shell># php demo/queue.php default PHP_Job
結果可以在螢幕上看到輸出:
Queued job 4ee7cefcb7df03ff5475fd450e2a5bea
即Job新增入佇列成功。
3. 檢視Job執行情況
php-resque同樣提供了檢視Job執行狀態的例子,直接執行:
shell># php demo/check_status.php 4ee7cefcb7df03ff5475fd450e2a5bea
可以看到輸出:
Tracking status of 10de5352387ba7212bc0d4e8975a3523. Press [break] to stop.
Status of 4ee7cefcb7df03ff5475fd450e2a5bea is: 1
Status of 4ee7cefcb7df03ff5475fd450e2a5bea is: 1
Status of 4ee7cefcb7df03ff5475fd450e2a5bea is: 1
我們剛才建立的Job執行狀態為1。在Resque中,一個Job有以下4中狀態:
Resque_Job_Status::STATUS_WAITING = 1; (等待)
Resque_Job_Status::STATUS_RUNNING = 2; (正在執行)
Resque_Job_Status::STATUS_FAILED = 3; (失敗)
Resque_Job_Status::STATUS_COMPLETE = 4; (結束)
由於沒有執行Worker,所以剛才建立的Job還是等待狀態。
4. 執行Worker
shell># vim demo/resque.php
date_default_timezone_set('GMT');
require 'job.php';
require '../bin/resque';
可以看到一個Worker至少需要兩部分:
1.可以直接包含Job類檔案,也可以使用php的自動載入機制,指定好Job Class所在路徑並能實現自動載入。
2.包含Resque中預設的Worker: bin/resque
在cli方式下執行:
shell># QUEUE=default php demo/resque.php
前面的QUEUE部分是設定的環境變數,我們指定當前的Worker只負責處理default佇列。也可以使用
shell># QUEUE=* php demo/resque.php
來處理所有的佇列。
執行後,可以看到輸出:
[notice] Starting worker s3:19060:default
[notice] Starting work on (Job{default} | ID: 4ee7cefcb7df03ff5475fd450e2a5bea | PHP_Job | [{"time":1378073476,"array":{"test":"test"}}])
Start job! -> Job ended! //Job的執行結果
[notice] (Job{default} | ID: 4ee7cefcb7df03ff5475fd450e2a5bea | PHP_Job | [{"time":1378073476,"array":{"test":"test"}}]) has finished
使用ps指令檢查一下:
shell># ps aux | grep resque
可以看到有一個php的守護程序已經在運行了
root 19060 0.0 0.6 209680 11768 pts/0 S+ 06:12 0:01 php demo/resque.php
任務執行完畢後,同時螢幕可以看到輸出結果!
至此利用Redis + php-resque實現訊息佇列的演示全部完成。
5. 參考資料
http://avnpc.com/pages/run-background-task-by-php-resque
http://kamisama.me/2012/10/09/background-jobs-with-php-and-resque-part-1-introduction/