Laravel 的 queue worker 與 Horizon 需要透過 artisan queue:work 在背景執行,若可以的話,再使用 systemd 或 supervisor 來監控運作狀態。
不過 systemd 和 supervisor 都需要 root 權限來操作,說起來蠻麻煩的,所以寫了一小段 shell script 來啟動與停止,沒辦法在 worker 中斷時 restart,但可以做 graceful start & shutdown。
啟動 queue worker:
./artisan queue:work \
--no-interaction --no-ansi >> storage/logs/queue.log 2>&1 &
# 透過 $? 來檢查指令執行是否成功
if [ $? -ne 0 ]; then
echo "FAILED !"
else
echo "OK"
fi
停止所有的 queue worker:
# queue:restart 會送訊號給所有的 worker 來 graceful shutdown
./artisan queue:restart --quiet --no-ansi
# 檢查是否所有的 proccess 都停止
while [ 1 ]; do
QUERY="$(ps -ef | grep queue:work | grep -v grep)"
if [ -z "${QUERY}" ]; then
break
else
sleep 1
fi
done
echo "OK"
Laravel Horizon 的操作相對簡單一些。
啟動 Horizon:
./artisan horizon \
--quiet --no-interaction --no-ansi >> storage/logs/horizon.log 2>&1 &
if [ $? -ne 0 ]; then
echo "FAILED !"
else
echo "OK"
fi
停止 Horizon:
artisan horizon:terminate --quiet --no-interaction --no-ansi
# 檢查 proccess 是否終止
while [ 1 ]; do
QUERY="$(ps -ef | grep horizon | grep -v grep)"
if [ -z "${QUERY}" ]; then
echo "OK"
else
sleep 1
fi
done
queue:restart 字面上看起來是重新啟動,好像不算是停止?
文字上是「重新啟動」,但自己測試時,僅會停止現有的 worker 但不會再次 start
剛剛翻了一下 code
artisan queue:restart的 source file 在Illuminate\Queue\Console\RestartCommand.php,執行以後,會在 cache 寫一個 timestamp。而
Illuminate\Queue\Worker.php的getTimestampOfLastQueueRestart中會去檢查 cache data,但是在哪裡會中斷、重新執行我還沒追到,這個檔案太肥了 Orz看起來是在
Worker.php的stopIfNecessary()中,會停止,但是似乎不會啟動另外 worker 啟動時,會去檢查 cache 取得 queue 停止的時間,應該是透過這個機制取得最後執行的 job(s)
唔 …. 好像應該加個
nohup…