選用Queue Driver
最簡單的方式是使用database作為job queue,像是mysql,但如果當job的數量一多,就會佔用到原有資料庫的資源,於是改選用redis,這個的壞處就是job durable的問題,我們後續再提。
Redis 設定方式
首先確保你的機器上安裝了redis,接著在專案中設定redis連線方式:
在.env檔加上
QUEUE_CONNECTION=redis
重新整理
php artisan config:clear
Horizon 監控平台
即使我們把job都寫好了,要怎麼方便開發人員監測?有幸,市面上針對redis queue有horizon這個免費套件可以使用,我們先來看一下有什麼好玩,再來看設定方式。
Dashboard
上方是一些統計數據,下方則是顯示worker狀態
Failed Jobs面板:
你能夠在手動retry失敗的job(他背後會再新增一個新的job到queue,會分配新的horizon id,如果想判斷可以看payload的retry_of跟uuid,假設job A失敗了,被手動retry兩次,則會新增job B跟job C,B,C paylaod會記錄這是來自重試A, 然後三者的uuid都會一樣)
設定方式
安裝套件
composer require laravel/horizon
發布資產(ex:前端頁面):
php artisan horizon:install
config/horizon.php 設定檔能玩玩看
啟用
php aritisan horizon
啟用成功後就會看到狀態為active囉
權限驗證
基本上這樣就完成了,但有個很重要的是你不會希望任何人都能用GET /horizon這個api去看你有哪些job,甚至去操作你的job!
在 app/Providers/HorizonServiceProvider.php
檔,我們可以定義誰可以訪問這個頁面,如果你有角色的話就可以在這做使用者的角色判斷,或是權限判斷都可以,附上官方範例,可自行在改寫:
/**
* Register the Horizon gate.
*
* This gate determines who can access Horizon in non-local environments.
*
* @return void
*/
protected function gate()
{
Gate::define('viewHorizon', function ($user) {
return in_array($user->email, [
'taylor@laravel.com',
]);
});
}
大功告成!
實驗看看
我們可以手動發起一個job,看看有沒有寫進redis當中。
我們在push job進redis queue的時候,horizon會把job資料重新打包成horizon版本的資料,我們來觀察一下每一個job裏面存的是什麼資料吧:
HGETALL "laravel_horizon:1630"
註解:這個1630是horizon給的id,job的獨一無二id要看uuid
如果是失敗的job會記錄:
- exception
- id
- payload
- failed_at
- status
- completed_at
- reserved_at
- queue (ex: default)
- connection (ex: redis)
- name (ex: “App\\Jobs\\NotifyUser”
- updated_at, created_at
Supervisor設定
雖然我們成功將job放入redis queue了,但是你有發現任務都沒有執行嗎?
我們可以使用Supervisor 來幫我們管理worker,worker負責處理任務。
在supervisor.d資料夾下(sudo find / -type d -name “supervisor.d” 2>/dev/null 來找到位置),新增xx專案.ini設定檔:
[program:supervisor的名稱]
process_name=%(program_name)s_%(process_num)02d
command=php /path/to/your-project/artisan horizon
autostart=true
autorestart=true
numprocs=8
redirect_stderr=true
stdout_logfile=~/your-project/storage/worker.log
stopwaitsecs=3600
接著啟用supervisor:
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start all
檢查是否有起動成功:
sudo supervisorctl status
踩雷經驗
active, 但是在horizon的supervisor不見了,但supervisor明明有正確運行。
解方:原來是因為沒有正確
php artisan horizon:terminate
終止在重啟後就正常吃到了