[ Laravel 5.2 文檔 ] 服務 -- 隊列

來源:互聯網
上載者:User

1、簡介

Laravel佇列服務為各種不同的後台隊列提供了統一的API。隊列允許你延遲耗時任務(例如發送郵件)的執行,從而大幅提高web請求速度。

1.1 配置

隊列設定檔存放在 config/queue.php。在該檔案中你將會找到架構內建的每一個隊列驅動的串連配置,包括資料庫、 Beanstalkd、 IronMQ、 Amazon SQS、 Redis以及同步(本地使用)驅動。其中還包含了一個null隊列驅動以拒絕隊列任務。

1.2 隊列驅動預備知識

資料庫

為了使用 database隊列驅動,需要一張資料庫表來存放任務,要產生建立該表的遷移,運行Artisan命令 queue:table,遷移被建立好了之後,使用 migrate命令運行遷移:

php artisan queue:tablephp artisan migrate

其它隊列依賴

下面是以上列出隊列驅動需要安裝的依賴:

  • Amazon SQS: aws/aws-sdk-php ~3.0
  • Beanstalkd: pda/pheanstalk ~3.0
  • Redis: predis/predis ~1.0

2、編寫任務類

2.1 產生任務類

預設情況下,應用的所有隊列任務都存放在 app/Jobs目錄。你可以使用Artisan CLI產生新的隊列任務:

php artisan make:job SendReminderEmail

該命令將會在 app/Jobs目錄下產生一個新的類,並且該類實現了 Illuminate\Contracts\Queue\ShouldQueue介面,告訴Laravel該任務應該被推送到隊列而不是同步運行。

2.2 任務類結構

任務類非常簡單,正常情況下只包含一個當隊列處理該任務時被執行的 handle方法,讓我們看一個任務類的例子:

user = $user;    }    /**     * 執行任務     *     * @param  Mailer  $mailer     * @return void     */    public function handle(Mailer $mailer)    {        $mailer->send('emails.reminder', ['user' => $this->user], function ($m) {            //        });        $this->user->reminders()->create(...);    }}

在本例中,注意我們能夠直接將Eloquent模型傳遞到對列任務的建構函式中。由於該任務使用了 SerializesModelstrait,Eloquent模型將會在任務被執行是優雅地序列化和還原序列化。如果你的隊列任務在建構函式中接收Eloquent模型,只有模型的主鍵會被序列化到隊列,當任務真正被執行的時候,隊列系統會自動從資料庫中擷取整個模型執行個體。這對應用而言是完全透明的,從而避免序列化整個Eloquent模型執行個體引起的問題。

handle方法在任務被隊列處理的時候被調用,注意我們可以在任務的 handle方法中進行依賴注入。Laravel服務容器會自動注入這些依賴。

出錯

如果任務被處理的時候拋出異常,則該任務將會被自動釋放回隊列以便再次嘗試執行。任務會持續被釋放知道嘗試次數達到應用允許的最大次數。最大嘗試次數通過Artisan任務 queue:listen或 queue:work上的 --tries開關來定義。關於運行隊列監聽器的更多資訊可以在下面看到。

手動釋放任務

如果你想要手動釋放任務,產生的任務類中內建的 InteractsWithQueuetrait提供了釋放隊列任務的 release方法,該方法接收一個參數——同一個任務兩次運行之間的等待時間:

public function handle(Mailer $mailer){    if (condition) {        $this->release(10);    }}

檢查嘗試運行次數

正如上面提到的,如果在任務處理期間發生異常,任務會自動釋放回隊列中,你可以通過 attempts方法來檢查該任務已經嘗試運行次數:

public function handle(Mailer $mailer){    if ($this->attempts() > 3) {        //    }}

3、推送任務到隊列

預設的 Laravel 控制器位於 app/Http/Controllers/Controller.php並使用了 DispatchesJobstrait。該trait提供了一些允許你方便推送任務到隊列的方法,例如 dispatch方法:

dispatch(new SendReminderEmail($user));    }}

DispatchesJobs Trait

當然,有時候你想要從應用中路由或控制器之外的某些地方分發任務,因為這個原因,你可以在應用的任何類中包含 DispatchesJobstrait,從而擷取對分發方法的訪問,舉個例子,下面是使用該trait的樣本類:

    

dispatch方法

或者,你也可以使用全域的dispatch方法:

Route::get('/job', function () {    dispatch(new App\Jobs\PerformTask);    return 'Done!';});

為任務指定隊列

你還可以指定任務被發送到的隊列。

根據任務被推送到的不同隊列,你可以對隊列任務進行“分類”,甚至優先考慮分配給多個隊列的worker數目。這並不會如隊列設定檔中定義的那樣將任務推送到不同隊列“串連”,而只是在單個串連中發送給特定隊列。要指定該隊列,使用任務執行個體上的 onQueue方法,該方法由 Laravel 內建的基類 App\Jobs\Job中的 Illuminate\Bus\Queueabletrait提供:

onQueue('emails');        $this->dispatch($job);    }}

3.1 延遲任務

有時候你可能想要延遲隊列任務的執行。例如,你可能想要將一個註冊15分鐘後給消費者發送提醒郵件的任務放到隊列中,可以通過使用任務類上的 delay方法來實現,該方法由 Illuminate\Bus\Queueabletrait提供:

delay(60);        $this->dispatch($job);    }}

在本例中,我們指定任務在隊列中開始執行前延遲60秒。

注意:Amazon SQS服務最大延遲時間是15分鐘。

3.2 任務事件

任務完成事件

Queue::after方法允許你在隊列任務執行成功後註冊一個要執行的回呼函數。在該回調中我們可以添加日誌、統計資料。例如,我們可以在Laravel內建的 AppServiceProvider中添加事件回調:

    

4、運行隊列監聽器

啟動任務監聽器

Laravel 包含了一個 Artisan 命令用來運行被推送到隊列的新任務。你可以使用 queue:listen命令運行監聽器:

php artisan queue:listen

還可以指定監聽器使用哪個隊列串連:

php artisan queue:listen connection

注意一旦任務開始後,將會持續運行直到手動停止。你可以使用一個過程監視器如Supervisor來確保隊列監聽器沒有停止運行。

隊列 優先順序

你可以傳遞逗號分隔的隊列串連列表到 listen任務來設定隊列優先順序:

php artisan queue:listen --queue=high,low

在本例中, high隊列上的任務總是在從 low隊列移動任務之前被處理。

指定任務逾時參數

你還可以設定每個任務允許啟動並執行最大時間(以秒為單位):

php artisan queue:listen --timeout=60

指定隊列睡眠時間

此外,可以指定輪詢新任務之前的等待時間(以秒為單位):

php artisan queue:listen --sleep=5

需要注意的是隊列只會在隊列上沒有任務時“睡眠”,如果存在多個有效任務,該隊列會持續運行,從不睡眠。

4.1 Supervisor配置

Supervisor為Linux作業系統提供的進程監視器,將會在失敗時自動重啟 queue:listen或 queue:work命令,要在Ubuntu上安裝Supervisor,使用如下命令:

sudo apt-get install supervisor

Supervisor設定檔通常存放在 /etc/supervisor/conf.d目錄,在該目錄中,可以建立多個設定檔指示Supervisor如何監視進程,例如,讓我們建立一個開啟並監視 queue:work進程的 laravel-worker.conf檔案:

[program:laravel-worker]process_name=%(program_name)s_%(process_num)02dcommand=php /home/forge/app.com/artisan queue:work sqs --sleep=3 --tries=3 --daemonautostart=trueautorestart=trueuser=forgenumprocs=8redirect_stderr=truestdout_logfile=/home/forge/app.com/worker.log

在本例中, numprocs指令讓Supervisor運行8個 queue:work進程並監視它們,如果失敗的話自動重啟。設定檔建立好了之後,可以使用如下命令更新Supervisor配置並開啟進程:

sudo supervisord -c /etc/supervisord.confsudo supervisorctl -c /etc/supervisor/supervisord.confsudo supervisorctl rereadsudo supervisorctl updatesudo supervisorctl start laravel-worker:*

要瞭解更多關於Supervisor的使用和配置,查看 Supervisor文檔。此外,還可以使用Laravel Forge從web介面方便地自動設定和管理Supervisor配置。

4.2 後台隊列監聽器

Artisan命令 queue:work包含一個 --daemon選項來強制隊列worker持續處理任務而不必重新啟動架構。相較於 queue:listen命令該命令對CPU的使用有明顯降低:

php artisan queue:work connection --daemonphp artisan queue:work connection --daemon --sleep=3php artisan queue:work connection --daemon --sleep=3 --tries=3

正如你所看到的, queue:work任務支援大多數 queue:listen中有效選項。你可以使用 php artisan help queue:work任務來查看所有有效選項。

後台隊列監聽器編碼考慮

後台隊列worker在處理每個任務時不重啟架構,因此,你要在任務完成之前釋放資源,舉個例子,如果你在使用GD庫操作圖片,那麼就在完成時使用 imagedestroy釋放記憶體。

類似的,資料庫連接應該在後台長時間運行完成後斷開,你可以使用 DB::reconnect方法確保擷取了一個新的串連。

4.3 部署後台隊列監聽器

由於後台隊列worker是常駐進程,不重啟的話不會應用代碼中的更改,所以,最簡單的部署後台隊列worker的方式是使用部署指令碼重啟所有worker,你可以通過在部署指令碼中包含如下命令重啟所有worker:

php artisan queue:restart

該命令會告訴所有隊列worker在完成當前任務處理後重啟以便沒有任務被遺漏。

注意:這個命令依賴於緩衝系統重啟進度表,預設情況下,APC在CLI任務中無法正常工作,如果你在使用APC,需要在APC配置中添加 apc.enable_cli=1。

5、處理失敗任務

由於事情並不總是按照計劃發展,有時候你的隊列任務會失敗。別擔心,它發生在我們大多數人身上!Laravel包含了一個方便的方式來指定任務最大嘗試執行次數,任務執行次數達到最大限制後,會被插入到 failed_jobs表,失敗任務的名字可以通過設定檔 config/queue.php來配置。

要建立一個 failed_jobs表的遷移,可以使用 queue:failed-table命令:

php artisan queue:failed-table

運行隊列監聽器的時候,可以在 queue:listen命令上使用 --tries開關來指定任務最大可嘗試執行次數:

php artisan queue:listen connection-name --tries=3

5.1 失敗任務事件

如果你想要註冊一個隊列任務失敗時被調用的事件,可以使用 Queue::failing方法,該事件通過郵件或 HipChat通知團隊。舉個例子,我麼可以在Laravel內建的 AppServiceProvider中附件一個回調到該事件:

    

任務類的失敗方法

想要更加細粒度的控制,可以在隊列任務類上直接定義 failed方法,從而允許你在失敗發生時執行指定動作:

    

5.2 重試失敗任務

要查看已插入到 failed_jobs資料表中的所有失敗任務,可以使用Artisan命令 queue:failed:

php artisan queue:failed

該命令將會列出任務ID,串連,對列和失敗時間,任務ID可用於重試失敗任務,例如,要重試一個ID為5的失敗任務,要用到下面的命令:

php artisan queue:retry 5

要重試所有失敗任務,使用如下命令即可:

php artisan queue:retry all

如果你要刪除一個失敗任務,可以使用 queue:forget命令:

php artisan queue:forget 5

要刪除所有失敗任務,可以使用 queue:flush命令:

php artisan queue:flush
  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.