Laravel之隊列

一.配置

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

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

 

二.依賴

1.數據庫依賴
爲了使用database 隊列驅動,須要一張數據庫表來存聽任務,要生成建立該表的遷移,運行 Artisan 命令queue:table ,遷移被建立好了以後,使用migrate 命令運行遷移:redis

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 該任務應該被推送到隊列而不是同步運行。app

 

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秒後次執行ide

 

四.推送任務

1.控制器中:this

$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.其餘地方使用 spa

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

  

整體而言,任務和事件的相同之處都是須要觸發/推送;不一樣之處可能在於,任務通常是耗時操做,放入隊列較好;事件通常不是耗時操做,固然事件也能夠是耗時操做,也能放入隊列.

相關文章
相關標籤/搜索