※ 本文為 dinos.bbs. 轉寄自 ptt.cc 更新時間: 2012-08-31 12:04:02
看板 PHP
作者 標題 [分享] 輕巧的 queue 系統 PHP-Resque
時間 Mon Jan 16 20:07:43 2012
網誌好讀版:
http://blog.hsatac.net/2012/01/php-resque-introduction/
[Resque](https://github.com/defunkt/resque) 是 Github 基於 Redis 開
defunkt/resque · GitHub
resque - Resque is a Redis-backed Ruby library for creating background jobs, placing them on multiple queues, and processing them later. ...
resque - Resque is a Redis-backed Ruby library for creating background jobs, placing them on multiple queues, and processing them later. ...
真的非常單純簡潔,充分利用 Redis 的特性。更多介紹可以看[原作者的
Blog](https://github.com/blog/542-introducing-resque)
[PHP-Resque](https://github.com/chrisboulton/php-resque) 是把
chrisboulton/php-resque · GitHub
PHP port of resque (Workers and Queueing). Contribute to php-resque development by creating an account on GitHub. ...
PHP port of resque (Workers and Queueing). Contribute to php-resque development by creating an account on GitHub. ...
甚至連 Redis 的 key 命名都一樣,因此也可以使用 Ruby 版本的
[resque-web](https://github.com/defunkt/resque-web) 來監控
defunkt/resque-web · GitHub
Sinatra-based web UI for Resque. Contribute to resque-web development by creating an account on GitHub. ...
Sinatra-based web UI for Resque. Contribute to resque-web development by creating an account on GitHub. ...
## 設計
Resque 的設計有兩個角色: Job 和 Worker。 每個 Job 都是定義成類別,
新增 Job 的時候會將 Job 的類別和相關參數 json_encode 後儲存到不同的
queue 裡面,而 Worker(s) 則會依序從 redis 讀取 Job 出來執行。
新增 Job 的時候會將 Job 的類別和相關參數 json_encode 後儲存到不同的
queue 裡面,而 Worker(s) 則會依序從 redis 讀取 Job 出來執行。
執行的時候並不是這個 Worker 本身去執行,而是會 fork 一個 process 來
執行。這樣設計是為了避免時間一長, Worker 的記憶體管理不良導致卡死
的狀況。
執行。這樣設計是為了避免時間一長, Worker 的記憶體管理不良導致卡死
的狀況。
讀取 queue 時會依據你啟動 worker 的時候給的 queue 順序來讀取,因此
優先權較高的 queue 要設定在前面。 Redis 可以是單機或 RedisCluster。
而許多不同伺服器上可以按需求部屬執行不同 queue 的 worker。
優先權較高的 queue 要設定在前面。 Redis 可以是單機或 RedisCluster。
而許多不同伺服器上可以按需求部屬執行不同 queue 的 worker。
以下先來介紹如何使用 PHP-Resque:
## 安裝 PHP-Resque
安裝非常容易,只要 `git clone
https://github.com/chrisboulton/php-resque.git` 下來,放到你想要的
chrisboulton/php-resque · GitHub
PHP port of resque (Workers and Queueing). Contribute to php-resque development by creating an account on GitHub. ...
PHP port of resque (Workers and Queueing). Contribute to php-resque development by creating an account on GitHub. ...
行就可以了。
## 環境變數
PHP-Resque 支援的環境變數有:
* QUEUE - 這個是必要的,會決定 worker 要執行什麼任務,重要的在前,
例如
任務。
例如
QUEUE=notify,mail,log
。也可以設定為 QUEUE=*
表示執行所有任務。
* APP_INCLUDE - 這也可以說是必要的,因為 Resque 的 Job 都是寫成物件
,那 worker 執行的時候當然要把物件的檔案引入進來。可以設成
APP_INCLUDE=require.php
再在 require.php 中引入所有 Job 的 Class檔案即可。
* COUNT - 設定 worker 數量,預設是1
COUNT=5
。* REDIS_BACKEND - 設定 Redis 的 ip, port。如果沒設定,預設是連
localhost:6379
。* LOGGING, VERBOSE - 設定 log,
VERBOSE=1
即可。* VVERBOSE - 比較詳細的 log,
VVERBOSE=1
debug 的時候可以開出來看。
* INTERVAL - worker 檢查 queue 的間隔,預設是五秒
INTERVAL=5
。* PIDFILE - 如果你是開單 worker,可以指定 PIDFILE 把 pid 寫入,例如
PIDFILE=/var/run/resque.pid
。有一個 Resque 支援,但 PHP-Resque 沒有的參數叫
BACKGROUND
可以把resque 丟到背景執行。不過這個其實不太重要,有需要的話自己加個
php resque.php &
就可以了。所以,你的指令最後可能會變這樣:
QUEUE=* APP_INCLUDE=require.php COUNT=5 VVERBOSE=1 php resque.php
如果覺得太長,可以寫一支啟動 script 來輔助你,我有寫一支可供參考:
https://gist.github.com/1619972
## 使用 PHP-Resque
把檔案抓下來以後一定想先試驗看看的,確定你的 redis-server 都有正常
啟動後,在 demo 資料夾下面有幾個檔案可以先試驗看看。
切到 demo 目錄後,執行
VVERBOSE=1 QUEUE=* php resque.php
應該會看到 resque 已經開始執行了。
執行
php queue.php PHP_Job
、 php queue.php Bad_PHP_Job
、php queue.php Long_PHP_Job
、 php queue.php PHP_Error_Job
可以把工作丟進 queue 裡面,看看執行的結果。
後面帶的名稱其實就是 Job class 的名稱,所以 PHP-Resque 在執行時也要
把相關的 class 檔案設定在 APP_INCLUDE 引入才行。
Job 的 class 很簡單,大概長這樣:
<?php
class My_Job
{
public function perform()
{
// Work work work
echo $this->args['name'];
}
}
?>
只要定義 perform 方法, Worker 就會把 Job new 出來以後執行 perform
。
當然,也可以定義
將 Job 塞入 queue 的方式是:
setUp()
和 tearDown()
方法,前者會在perform()
執行前執行,後者會在 perform()
執行後執行。將 Job 塞入 queue 的方式是:
<?php
require_once 'lib/Resque.php';
Resque::setBackend('localhost:6379');
$args = array(
'name' => 'Chris'
);
Resque::enqueue('default', 'My_Job', $args);
?>
其中第一個參數
default
就是你的 queue 名稱,例如你可以設定notify, mail, image 之類,至於為什麼要這樣設計,在後面的篇幅再敘述
。
PHP-Resque 的使用方法大致就是這樣,接下來講一些其他的小細節。
## Hooks
PHP-Resque 可以定義 Event Hooks 讓你能在相對應的事件發生時執行你想
要的動作。支援的事件有很多,請各位自行參考原專案的 README。在專案目
錄下的 extra 目錄下有 sample.plugin.php 可以看 Event hook 的範例寫
法。
要的動作。支援的事件有很多,請各位自行參考原專案的 README。在專案目
錄下的 extra 目錄下有 sample.plugin.php 可以看 Event hook 的範例寫
法。
有一點需要注意的是,很直覺我們會把這隻 sample.plugin.php 丟到
APP_INCLUDE 變數中,這樣沒錯,但要注意跟 enqueue 有關的 event 並不
是由 worker 來觸發,因此你在新增 Job 的那段程式也需要引入
sample.plugin.php 才能觸發到
AFTERENQUEUE
。## 監控
### resque-web
前面有提到可以直接使用 resque-web 來監控 PHP-Resque 的狀態,相當建
議使用,非常清楚易懂,要看 Redis 相關的數據也可以看,不用進
redis-cli 自己打指令。
安裝方法:
gem install resque
執行:
首頁有 live reload 按鈕可以按, debug 時非常方便。
### Supervisord
resque-web -p 3000
即可運行在 3000 port。首頁有 live reload 按鈕可以按, debug 時非常方便。
### Supervisord
在專案的 extra 目錄下另有 resque.monit 檔案,這是供
[Supervisord](http://supervisord.org/) 使用的設定檔。他會在 worker
吃掉 300MB 以上的記憶體,或者是跑了 10 次輪迴後砍掉重開。可以參考
看看。
## 佈署
之前提到可以除了預設的 default 以外,還可以設定不同的 queue,為什麼
要這樣做呢?除了執行優先權外,(撈 queue 時會按你給 worker 的設定,
在前面 queue 的會先撈,就會先執行到) 還有多伺服器部屬的原因。
要這樣做呢?除了執行優先權外,(撈 queue 時會按你給 worker 的設定,
在前面 queue 的會先撈,就會先執行到) 還有多伺服器部屬的原因。
假如今天你有個 queue 專門要處理使用者圖片的東西,當然一般圖片會有自
己的伺服器。於是在你的主 web 伺服器上你就可以執行
QUEUE=notify,mail
而在圖片伺服器上就可以執行 QUEUE=images
的worker。
另外就是由於 Worker 啟動時已經將 APP_INCLUDE 的檔案都讀入,持續執行
。因此如果有修改引入的 Job 或 hook plugin 等檔案的話,deploy 時要將
worker 停止,重新啟動才會讀入新的 APP_INCLULDE 檔案。
。因此如果有修改引入的 Job 或 hook plugin 等檔案的話,deploy 時要將
worker 停止,重新啟動才會讀入新的 APP_INCLULDE 檔案。
## 已知問題
首先,PHP-Resque 使用的是
[Redisent](https://github.com/jdp/redisent) 這套 Redis interface。
jdp/redisent · GitHub
A Redis interface for the modest. Contribute to redisent development by creating an account on GitHub. ...
A Redis interface for the modest. Contribute to redisent development by creating an account on GitHub. ...
[phpredis](http://code.google.com/p/phpredis/) 同樣都定義了
RedisException 這個類別,所以會衝突,必須把 phpredis 移除才能使用。
再來,在部屬時常常 REDIS_BACKEND 是設到別台機器的,而且一般我們都會
開不只一個 worker ,這時候有一個已知 issue 就是有時 lpop 拉回來的
Job 錯誤,是一個陣列,導致噴出 json_decode 的錯誤,而且這個 Job 就
不會執行,會 missing 。 (see
Job 錯誤,是一個陣列,導致噴出 json_decode 的錯誤,而且這個 Job 就
不會執行,會 missing 。 (see
(https://github.com/chrisboulton/php-resque/issues/32))
Issue #32: Multiple Workers = Lost jobs? · chrisboulton/php-resque · GitHub
As per a comment on issue #30, I'm opening this issue in order to help gather more info and find a fix for the bug.
I observed that when deploying multiple workers, some jobs dont get processed...
Basically the test I did was:
watch output and number of jobs, launch 5 workers.
Enqueue 10 jobs. numbe ...
As per a comment on issue #30, I'm opening this issue in order to help gather more info and find a fix for the bug.
I observed that when deploying multiple workers, some jobs dont get processed...
Basically the test I did was:
watch output and number of jobs, launch 5 workers.
Enqueue 10 jobs. numbe ...
目前還不清楚確實問題所在,不過有一個 workaround 的解法是,不要用
COUNT=5
去開,而是設 COUNT=1
然後執行 5 次,就不會有這個問題產生。
## 結語
Resque 真的是一個很棒很輕巧的設計,感謝有人把它 porting 到 PHP 。希
望越來越多人來使用,一起來發展維護 PHP-Resque。
--
■英雄聯盟大絕使用時機■
1.生命身體受暴行脅迫,非使用大絕不能扺抗或自衛時。
2.敵方逼戰,非使用大絕不能制止時。
3.所警衛之隊友、野怪、砲塔、兵營受危害脅迫,非使用大絕不能保護時。
4.因防衛駐守之砲塔、叢林、兵營受襲擾或擅闖,非使用大絕不能制止時。
5.敵方殘血脫逃,非使用大絕不能制止時。
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 114.43.143.240
※ 編輯: hSATAC 來自: 114.43.143.240 (01/16 20:17)
推 :寫得真詳細1F 01/16 21:50
推 :謝大大無私的分享2F 01/17 00:09
→ :推帥哥 cat3F 01/17 00:29
推 :推4F 01/18 17:28
推 :你也是鄉民XD 我是Ting5F 01/19 22:45
推 :推. Markdown 真好用6F 01/20 01:46
推 :推薦7F 01/26 15:34
--
※ 看板: dinos 文章推薦值: 0 目前人氣: 0 累積人氣: 579
瞎
guest
回列表(←)
分享