使用场景:
有些任务并不需要及时运行,就可以将其写入队列,从而不影响主业务逻辑的进程。
如:此篇博文发布成功后推送消息给其关注的用户。假如粉丝很多,肯定不能将发布博文与推送通知的逻辑捆绑在一起,不然服务器资源卡死。
下面简单介绍如何使用
1.配置队列(config/queue.php)
框架所支持的队列驱动的配置都有。包括:database,Beanstalkd,Amazon SQS,Redis,和一个同步(本地使用)的驱动。还有一个名为 null 的驱动表明不使用队列任务。
ps:这里的队列驱动 可以理解为存储队列任务的载体 :下面截图介绍
2.在.env 文件中配置使用的队列(此处以redis做演示)
QUEUE_DRIVER=redis
3.创建队列表(cmd运行)
php artisan queue:table(以database为驱动要运行,redis驱动数据直接插入redis)
php artisan migrate
php artisan queue:failed-table
php artisan migrate
简单介绍: 第一步会新建
database/migrations/{timestamp}_create_failed_jobs_table.php 文件(表结构)
接着使用 migrate 命令生成表
失败任务#
有时候队列中的任务会失败。Laravel 内置了一个方便的方式来指定任务重试的最大次数。当任务超出这个重试次数后,它就会被插入到 failed_jobs 数据表里面
###最后运行成功,会在数据库中出现如下表:
4.配置队列任务最大重试次数,或者单任务最大执行时间,有两种方法
方法一:artisan命令,增加—tries或者 —timeout
php artisan queue:listen --tries=3 //失败任务尝试3次
php artisan queue:listen --timeout=60 //每个任务运行最大时间不超过60秒
方法二:在Job控制器,任务类中加入变量定义
PS:优先级
当在类配置了,那么 artisan命令的配置将无效,即任务类配置优先
5.生成任务类
使用以下 Artisan 命令来生成一个新的队列任务:
php artisan make:job SendEmail
该命令会在 app/Jobs 目录下生成一个新的类:
app/Jobs/SendEmail.php
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
// use Exception;
class SendEmail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* 任务最大尝试次数。
*
* @var int
*/
public $tries = 3;
/**
* 任务运行的超时时间。
*
* @var int
*/
public $timeout = 180;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
try {
$error = 'Always throw this error';
throw new Exception($error);
// 从这里开始,tra 代码块内的代码将不会被执行
echo 'Never executed';
file_put_contents(storage_path('logs/queue.log'),'['.date('Y-m-d : h:i:s',time()).']'.'队列执行success'."\r\n",FILE_APPEND);
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(),'
';
}
}
}
6.任务下发
再控制器中直接使用
SendEmail::dispatch();
注意:要引入SendEmail 类
use App\Jobs\SendEmail;
7.测试(监听队列任务)
php artisan queue:listen
如果还未监听 运行第六部会将任务一直存储在队列驱动的数据库里
如:
redis
或者database
当运行第七步,运行队列,会依次执行
由于此处我设置了tries=3 并且在job类里注释了// use Exception;
队列任务会在尝试三次后失败写入failed_job表中
最后 补充一点
在app\Providers\AppServiceProvider.php中
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Queue;
use Illuminate\Queue\Events\JobProcessed;
use Illuminate\Queue\Events\JobProcessing;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Queue::before( function (JobProcessing $event) {
\Log::info("处理任务前");
});
Queue::after( function (JobProcessed $event) {
\Log::info("处理任务后");
});
}
}
boot方法中添加after before 会在队列任务执行前后 先做处理