Laravel之隊列


一.配置

隊列配置文件存放在config/queue.php 。在該文件中你將會找到框架自帶的每一個隊列驅動的連接配置,包括數據庫、Beanstalkd、 IronMQ、 Amazon SQS、 Redis 以及同步(本地使用)驅動。其中還包含了一個 null 隊列驅動以拒絕隊列任務。

默認是sync,即同步的,直接處理,無隊列.要將其修改為對應的類型,如database等

 

二.依賴

1.數據庫依賴
為了使用database 隊列驅動,需要一張數據庫表來存放任務,要生成創建該表的遷移,運行 Artisan 命令queue:table ,遷移被創建好了之后,使用migrate 命令運行遷移:

php artisan queue:table
php artisan migrate

  

2.其他隊列類型依賴
下面是以上列出隊列驅動需要安裝的依賴:
• Amazon SQS: aws/aws-sdk-php ~3.0
• Beanstalkd: pda/pheanstalk ~3.0
• IronMQ: iron-io/iron_mq ~2.0
• Redis: predis/predis ~1.0

 

三.生成任務類

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

php artisan make:job SendReminderEmail --queued

  

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

 

2.SendReminderEmail.php代碼如下:

<?php

namespace App\Jobs;

use Illuminate\Support\Facades\Log;
use App\Jobs\Job;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Bus\SelfHandling;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\Models\User;

class SendReminderEmail extends Job implements SelfHandling, ShouldQueue
{
    use InteractsWithQueue, SerializesModels;

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

    /**
     * 處理任務.
     *
     * @return void
     */
    public function handle()
    {
        Log::alert('我是來自隊列,發送了一個郵件',['id' => $this->user->id, 'name' => $this->user->name]);
    }
}

  

3.任務發生異常
a.任務在處理的時候發生異常,任務將被放回隊列.在下一次再被處理
b.判斷同一任務失敗的次數
$this->attempts() // 返回失敗次數
$this->release(50); // 將任務放回到隊列,50秒后次執行

 

四.推送任務

1.控制器中:

$user = Auth::user();
$this->dispatch((new SendReminderEmail($user))->delay(60)); //delay表示延遲隊列執行

// 也可以將任務推送到不同的隊列中
$this->dispatch((new SendReminderEmail($user))->onQueue('jobs'));

// 也可以從請求中分發任務
$this->dispatchFrom('App\Jobs\ProcessOrder', $request, [附加的參數]);

  

2.其他地方使用 

use DispatchesJobs;
......
$this->dispatch()

  

 

五.啟動隊列監聽

1.基本命令

php artisan queue:listen connection_name --queue=queue_name

php artisan queue:listen connection //指定連接,也就是不同隊列類型,如database,redis,在queue.php中配置

php artisan queue:listen --queue=high,low //指定隊列優先級,比如有限處理某隊列,多個隊列用,分割

php artisan queue:listen --timeout=60 //每個任務運行最大時間不超過60秒

php artisan queue:listen --sleep=5 //沒有任務的時候休眠5秒

php artisan queue:listen --tries=3 //失敗任務嘗試3次

 

queue:work 默認只執行一次隊列請求, 當請求執行完成后就終止;
queue:listen 監聽隊列請求,只要運行着,就能一直接受請求,除非手動終止;

 

2.作為系統進程運行

Supervisor

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

[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 --daemon
autostart=true
autorestart=true
user=forge
numprocs=8
redirect_stderr=true
stdout_logfile=/home/forge/app.com/worker.log

  

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

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-worker:*

  

3.后台隊列(守護進程)

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

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

  

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

注意點:
1.后台隊列 worker 在處理每個任務時不重啟框架,因此,你要在任務完成之前釋放資源,舉個例子,如果你在使用 GD 庫操作圖片,那么就在完成時使用imagedestroy 釋放內存。類似的,數據庫連接應該在后台長時間運行完成后斷開,你可以使用DB::reconnect 方法確保獲取了一個新的連接。

2.如果修改了代碼,在后台隊列中是無效的,必須重啟隊列
php artisan queue:restart
這個命令依賴於緩存系統重啟進度表,默認情況下,APC 在 CLI 任務中無法正常工作,如果你在使用 APC,需要在 APC 配置中添加apc.enable_cli=1 。

 

六.處理失敗任務

1.創建一個 failed_jobs 表的遷移

php artisan queue:failed-table

  

2.生成表

php artisan migrate

  

3.加重試次數限制

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

  

超過3次的任務將被移到failed_jobs表

4.也可以手動刪除一個任務

if ($this->attempts() == 1) {
            $this->delete();
}

  

5.添加失敗任務事件

a.AppServiceProvider中添加

/**
* 啟動應用服務
*
* @return void
*/
public function boot()
{
	Queue::failing(function ($connection, $job, $data) {
	// Notify team of failing job...
	});
}

  

b.在任務類中添加

/**
* 執行任務
*
* @param Mailer $mailer
* @return void
*/
public function handle(Mailer $mailer)
{
	//
}

/**
* 處理失敗任務
*
* @return void
*/
public function failed()
{
	// Called when the job is failing...
}

  

6.重試失敗任務

a.查看失敗的任務
php artisan queue:failed

b.重新執行失敗任務
php artisan queue:retry 5 //重新執行id為5的失敗任務

c.刪除失敗任務
php artisan queue:forget 5 //刪除id為5的失敗任務

d.刪除所有任務
php artisan queue:flush

  

總體而言,任務和事件的相同之處都是需要觸發/推送;不同之處可能在於,任務一般是耗時操作,放入隊列較好;事件一般不是耗時操作,當然事件也可以是耗時操作,也能放入隊列.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM