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

  

整体而言,任务和事件的相同之处都是须要触发/推送;不一样之处可能在于,任务通常是耗时操做,放入队列较好;事件通常不是耗时操做,固然事件也能够是耗时操做,也能放入队列.

相关文章
相关标签/搜索