近半月參與重寫一個微信公眾號後端系統,首次使用 Laravel 4.2 及其引以為傲的隊列服務。系統涉及多端交互、大量語音傳輸與處理,發現回應時間過長。前系統基於 Node.js + MongoDB,Node 天生非同步且有守護進程,無此問題;重寫勢必引入非同步流程,Queue 進入視野。
根據幾乎全英文的「中文文件」,Laravel 4.2 剛引入 Redis 作為隊列儲存,這是極佳消息。
Laravel 隊列服務與其他隊列系統無異,符合人類直覺的簡單流程:
因 PHP 是 URL 驅動的同步阻塞語言,Laravel 提供守護進程工具查詢並執行隊列任務。
配置檔 /app/config/queue.php 中的 Default Queue Driver 提供五種驅動:
插曲: Session 驅動千萬別用 MySQL,處理時間 1 秒起跳,看誰呢,說的就是你,1 秒哥!
隊列任務需建立獨立類別,無需繼承基類,因守護進程會獨立調用。筆者將額外服務獨立至 /app/services(已註冊至 composer.json 的 autoload.classmap),隊列類亦置於其中。
use Queue;
Queue::push('CurlJsonQueue', [
'url' => $url,
'json' => $json
]);
此為標準隊列推送流程。CurlJsonQueue 類位於 services 根目錄,屬頂層命名空間可直接調用;若需調用非頂層命名空間,可寫 App\OOXX。系統大量與微信伺服器交互,故獨立此類。
<?php
class CurlJsonQueue extends BaseController {
public function fire($job, $data)
{
$url = $data['url'];
$json = $data['json'];
parent::base_post_curl($url, $json);
$job->delete();
}
}
類別預設方法為 fire(),固定參數 $job 與 $data。筆者於 BaseController 封裝了 POST CURL 模組,故直接調用。小坑: 當時 base_post_curl() 設為 protected,導致 use BaseController 無效,必須繼承。
執行指令啟動守護進程:
php artisan queue:listen
測試環境可手動或開機啟動,生產環境需更穩健工具守護 Redis 與 PHP CLI 進程,筆者採用 Supervisor,安裝配置參考:SegmentFault 文章(文中有小坑請自行踩雷)。
全部配置完成,Redis 與 PHP CLI 跑起來,系統愉快運作!
'' 強制轉字串。上例 $url、$json 已用引號宣告型別,故無此問題。/ 前加雙反斜線 \\,對特殊操作可能造成影響。