一.配置
隊列配置文件存放在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
總體而言,任務和事件的相同之處都是需要觸發/推送;不同之處可能在於,任務一般是耗時操作,放入隊列較好;事件一般不是耗時操作,當然事件也可以是耗時操作,也能放入隊列.
