1. 程式人生 > 程式設計 >Laravel中使用Queue佇列技巧

Laravel中使用Queue佇列技巧

Laravel 佇列為不同的後臺佇列服務提供統一的 API,例如 Beanstalk,Amazon SQS,Redis,甚至其他基於關係型資料庫的佇列。佇列的目的是將耗時的任務延時處理,比如傳送郵件,從而大幅度縮短 Web 請求和相應的時間。

佇列配置檔案存放在 config/queue.php 。每一種佇列驅動的配置都可以在該檔案中找到,包括資料庫,Beanstalkd ,Amazon SQS,Redis,以及同步(本地使用)驅動。其中還包含了一個 null 佇列驅動用於那些放棄佇列的任務

為什麼使用佇列?

一般來說使用佇列是為了:

非同步
重試
複製程式碼

也許你還有其他的理由使用佇列,但是這應該是最基本的兩個原因。

什麼情況使用佇列?

瞭解了為什麼使用佇列,那麼一般有這麼幾類任務使用佇列:

耗時比較久的,比如上傳一個檔案後進行一些格式的轉化等。 需要保證送達率的,比如傳送簡訊,因為要呼叫別人的 api,總會有機率失敗,那麼為了保證送達,重試就必不可少了。 使用佇列的時候一定要想明白一個問題,這個任務到底是不是可以非同步,如果因為非同步會導致問題,那麼就要放棄使用佇列。

驅動的必要設定

database.php

在 database.php 配置檔案中對 redis 資料庫部分進行配置,預設有一個 default 連線,就用這個好了:)

根據這個預設連線中需要的配置項,編輯 .env 配置檔案,將其中的 REDIS_HOST、REDIS_PASSWORD、REDIS_PORT 填寫成自己伺服器中 Redis 的相應值。

queue.php

首先需要去 .env 中配置 QUEUE_DRIVER,因為現在打算用 Redis,所以配置成 redis。

接著配置 queue.php 裡 connections 部分的 redis 連線,其中 connection 對應的值就是 database.php 中 redis 的那個 default 連線。

資料庫

要使用 database 這個佇列驅動的話,你需要建立一個資料表來儲存任務。你可以用 queue:table 這個 Artisan

php artisan queue:table
複製程式碼

處理失敗的任務

有時候你佇列中的任務會失敗。不要擔心,本來事情就不會一帆風順。

Laravel 內建了一個方便的方式來指定任務重試的最大次數。當任務超出這個重試次數後,它就會被插入到 failed_jobs 資料表裡面。要建立 failed_jobs 表的遷移檔案,你可以用 queue:failed-table 命令,接著使用 migrate Artisan 命令生成 failed_jobs 表:

php artisan queue:failed-table
複製程式碼

命令來建立這個資料表的遷移。當遷移建立好以後,就可以用 migrate 這條命令來建立資料表:

php artisan migrate
複製程式碼

執行命令講解

php artisan queue:work --daemon --quiet --queue=default --delay=3 --sleep=3 --tries=3
複製程式碼
--daemon
複製程式碼

The queue:work Artisan command includes a --daemon option for forcing the queue worker to continue processing jobs without ever re-booting the framework. This results in a significant reduction of CPU usage when compared to the queue:listen command

總體來說,在 supervisor 中一般要加這個 option,可以節省 CPU 使用。

--quiet
複製程式碼

不輸出任何內容

--delay=3
複製程式碼

一個任務失敗後,延遲多長時間後再重試,單位是秒。這個值的設定我個人建議不要太短,因為一個任務失敗(比如網路原因),重試時間太短可能會出現連續失敗的情況。

--sleep=3
複製程式碼

去 Redis 中拿任務的時候,發現沒有任務,休息多長時間,單位是秒。這個值的設定要看你的任務是否緊急,如果是那種非常緊急的任務,不能等待太長時間。

--tries=3
複製程式碼

定義失敗任務最多重試次數。這個值的設定根據任務的重要程度來確定,一般 3 次比較適合。

建立任務

生成任務類

在你的應用程式中,佇列的任務類都預設放在 app/Jobs 目錄下。如果這個目錄不存在,那當你執行 make:job Artisan 命令時目錄就會被自動建立。你可以用以下的 Artisan 命令來生成一個新的佇列任務:

php artisan make:job Demo
複製程式碼

生成的類實現了 Illuminate\Contracts\Queue\ShouldQueue 介面,這意味著這個任務將會被推送到佇列中,而不是同步執行。

<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Facades\Log;

class Demo implements ShouldQueue
{
    use Dispatchable,InteractsWithQueue,Queueable,SerializesModels;

    public $param;
    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct($param = '')
    {
        $this->param = $param;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        Log::info('Hello,'.$this->param);
    }
}

複製程式碼

控制器程式碼

public function queue_demo()
{
    $num = rand(1,999999999);
    // 這個任務將被分發到預設佇列...
    DemoJob::dispatch($num);
}
複製程式碼

開啟佇列

php artisan queue:work --queue=default
複製程式碼

由於是本地,需要開啟監聽,當訪問到介面時,就會觸發佇列中的任務

線上的話需要用到supervisor的配置

Supervisor 配置

安裝 Supervisor

Supervisor 是一個 Linux 作業系統上的程式監控軟體,它會在 queue:listen 或 queue:work 命令發生失敗後自動重啟它們。在 Ubuntu 安裝 Supervisor,可以用以下命令:

sudo apt-get install supervisor
複製程式碼

{tip} 如果自己手動配置 Supervisor 聽起來有點難以應付,可以考慮使用 Laravel Forge,它能給你的 Laravel 專案自動安裝與配置 Supervisor。

配置 Supervisor

Supervisor 的配置檔案一般是放在 /etc/supervisor/conf.d 目錄下。在這個目錄中你可以建立任意數量的配置檔案來要求 Supervisor 怎樣監控你的程式。例如我們建立一個 laravel-worker.conf 來啟動與監控一個 queue:work 程式:

[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /home/forge/app.com/artisan queue:work sqs --sleep=3 --tries=3
autostart=true
autorestart=true
user=forge
numprocs=8
redirect_stderr=true
stdout_logfile=/home/forge/app.com/worker.log
複製程式碼

這個例子裡的 numprocs 命令會要求 Supervisor 執行並監控 8 個 queue:work 程式,並且在它們執行失敗後重新啟動。當然,你必須更改 command 命令的 queue:work sqs ,以顯示你所選擇的佇列驅動。

啟動 Supervisor 當這個配置檔案被建立後,你需要更新 Supervisor 的配置,並用以下命令來啟動該程式:

sudo supervisorctl reread

sudo supervisorctl update

sudo supervisorctl start laravel-worker:*
複製程式碼

更多有關 Supervisor 的設定與使用,請參考 Supervisor 官方檔案

具體示例程式碼參考github倉庫