php的消息隊列框架resque的使用小結

前段時間在開發一個量化交易系統,這是一個類似股票交易軟件的系統:股票價格變化後要實時在終端(APP)的行情價格頁面實時更新,如果用戶是在持倉頁面,還要計算持倉盈虧及預付款比例,因爲有一個強制平倉機制(當預付款比較低於30%時系統要自動觸發強制平倉),因爲行情波動非常快(有些產品一秒鐘內價格會變化五六次),所以當某個產品的價格變化時,要觸發一系統的行情推送(通過長連接)及盈虧計算操作。

因爲價格變動非常快,如果使用同步操作的話,很容易造成阻塞,所以用異步消息隊列是比較好的選擇,在網上查了一番,決定用resque來實現,試用了一下,發現網上所謂的resque教程大都是將它的demo代碼講解了一遍,坑很多,所以把我試用過程中遇到的問題統一做個記錄,一個是方便同樣正在嘗試使用resque的朋友,二是作爲自己的備忘錄,好,下面正式開始。

Part 1.安裝

網上很多教程的指引還是安裝源chrisboulton/php-resque版本的,實際上現在最新的版本應該是resque/php-resque源的, 用composer安裝的方法是,在composer.json文件中的require節點下添加”resque/php-resque:^1.2”,
在這裏插入圖片描述
然後執行composer install即可。

Part2.連接設置了密碼的redis

resque是基於redis的,所以沒有redis是運行不起來的,可能開發者初期沒有考慮到redis有設置了密碼的情況,所以我剛開始看網上的資料是有介紹怎樣解決這個問題的,但我把代碼簽出來後發現Resque::setBackend的方法是支持傳入auth參數的,於是以爲這個問題已經在目前的版本里解決了,實際上還是不行,如果你的redis裏設置了密碼,建議修改插件目錄下的resque/php-resque/lib/Resque.php這個文件,大概在68行將創建redis連接的代碼用以下代碼代替可以解決連接redis失敗的問題。

$redis = new Redis();
$redis->connect(self::$redisServer);
$redis->auth(self::$auth);
$redis->select(self::$redisDatabase);
self::$redis = $redis;

修改完後將redis的密碼通過setBackend方法的第三個參數傳入就可以了,示例:

Resque::setBackend('127.0.0.1', 1, \Config::$redis['option']['auth']);

Part3.運行

如果你看了其它網友的經驗分享,你會知道resque有三個角色:Queue、Worker、Job,Queue負責接收消息隊列,Worker負責任務調度,Job負責執行業務邏輯,用現實生活舉例就是像一個高鐵站一樣,Queue是售票廳、Worker是控制室、Job則是車隊,以下我也分三部分說下這個注意事項:

  • Queue:
    按照業務邏輯需要,Queue在何時何地執行都可以的,因爲作爲一個消息隊列,肯定要支持動態添加任務進去,有一點要注意的是,如果你的Job類有命名空間,一定要將完整的路徑寫進去,我在這裏卡了一下,以爲在Job類裏通過use引入了這個命名空間即可,但實際上行不通,必須在調用enqueue方法時傳入帶命名空間的路徑才能正常執行,下面是一個示例:
Resque::setBackend('127.0.0.1', 1, \Config::$redis['option']['auth']);
for($i = 1; $i < 10; $i++){
    Resque::enqueue('pushMarketPrice', '\site_pc\action\Job', ['newPrice' => 1367.85, 'rate' => 7.09]);
}
  • Worker
    從demo文件可以看出,Worker就是要加載Job類及bin下的resque文件,但demo裏並不是面向對象的寫法,如果要定義在一個類裏,可以參照以下寫法:
class Worker{
    /**
     * @router cli work
     */
    public function run(){
        require "../vendor/resque/php-resque/bin/resque";
    }
}

其中,require後面的路徑請修改爲相對你項目執行文件入口的路徑。

  • Job
    Job類就比較簡單,記着要實現一個perform方法就方法了,另外,demo裏沒有體現的一個細節是在Queue中傳入的參數怎樣獲取,其實很簡單,在perform方法通過$this->args就能拿到傳入的參數數組,非常方便。
class Job{
    public function perform(){
        Tools::logToDb('resque', $this->args);
    }
}

$this->args就是你此前在Queue中傳入的自定義參數數組了。

Part4.監控

怎樣判斷resque的狀態(是否在正常運行中)呢?還有如果已經在運行,怎樣重啓?可以通過查看進程的命令來達到這個目的,登錄系統後執行: ps -aux | grep resque
如果resque正在運行中,你看到的界面應該是這樣的:
在這裏插入圖片描述
其中,上圖橢圓形圈中的是進程ID,如果希望停止運行,可以使用kill -9 [進程id]來殺死進程,紅方框則是進程狀態,正在等待隊列中的任務。一有任務就會執行,至此,這個插件已經在正常運行了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章