Laravel Artisan Queues 佔用大量的 CPU

公司經手的專案中頻繁的使用了 Queue 來進行工作排程,當專案轉交給客戶測試之後,客戶提出了一個新的需求。希望能增加排程併行的數量,假設有 100 個工作要排入 Queues,希望能自動分派給 2 或 4 個序列同時運行,如此來縮短工作時間。

原本在測試環境中上述的架構運行都一切正常,但你也知道的,問題往往都在正式環境中爆發!

正式上線後,果不其然 Server 就爆了,查看原因後才發現,只要一透過 Supervisor 啟動 Laravel Artisan Queues,立馬 CPU 就往上飆升至 80 ~ 90 %,也難怪客戶都還沒做什麼其他動作,Server 就自己先掛掉陷入無回應的狀態。

有關 Laravel Artisan Queues、beanstalkd 及 supervisor 的使用,就不在這裡說明,雖然現在已經是 Laravel 5 了,但在 Laravel 4 的時候滿多人推薦可以參考這一篇《Production-Ready Beanstalkd with Laravel 4 Queues》

併行多條 Queues 序列 在 Laravel 的 config 中預設了 default 的序列,但將工作推到 Queues 時,其實是可以自行指定要推到哪一條序列,在前述的案例中,其實就是在工作排程時,自動分配至數個序列。

真正的 CPU 消耗者 將大量的工作排入 Queues 並不是消耗 CPU 的兇手,真正的元凶其實是 supervisor 配上不恰當的 Queue listen 或 Queue worker 指令。

為了要自動將排程的工作拉回來執行,一般會建議使用 supervisor 來自動重啟 Queue listen 或 Queue worker。透過簡單的測試就可以發現,Queue listen 或 Queue worker 本身運行的時候,就會佔據一些系統資源,如果正好排程中的工作也需要耗費大量運算的,當然是雪上加霜。

然其實 Queues 占用資源的問題早已有人反映,所以 Laravel 官方也已有處理。若去查看 help 就會發現 php artisan queue:work 有一些參數可以設定,只要透過恰當的設定參數,就可以避免系統資源被吃光的問題,所以說在操作之前,一定要詳閱說明書。 針對前述提到的專案,最後我們調整了 Supervisor 中 Laravel Queue worker 的設定,同樣會 listen 多條序列,但是參數設定上有些小差異。

php artisan queue:work --daemon --memory 512 --sleep 60 php artisan queue:work --daemon --queue queue_1st --sleep 10 php artisan queue:work --daemon --queue queue_2nd --sleep 10 php artisan queue:work --daemon --queue queue_3rd --sleep 10

第一個 worker 同樣 listen 預設的 default 序列,但是排定處理較複雜的工作,因此給予它較多的 memory。 其他的 worker 則是 listen 指定的序列,因為會有較多的小工作頻繁地被丟進來,因此 sleep 的時間比較短。

透過 memory 及 sleep 兩個參數,即能排除系統資源占用的問題。

參考資料: StackOverflow: Laravel Artisan Queues - high cpu usage

轉貼本文時禁止修改,禁止商業使用,並且必須註明來自「艦長,你有事嗎?」原創作者 Cheng Wei Chen,及附上原文連結。

工商服務

更多文章