一、先简单的说明下为什么要是用队列任务,因为公司项目涉及到了发邮件的功能,而邮件服务代理商和项目服务器在两个不同的国家,客户端上有发邮件的功能都会反应好几秒,因此想把发邮件这种实时性要求不高的功能单独拿出来,通过队列任务异步发送。
1、大致思路:
当功能中遇到发邮件的需求,将该发送请求包含的必要参数记录至某个队列中(mysql、redis、file均可)。
开启一个守护进程,一直监控该任务队列,发现有任务进来后,获取任务数据,然后发送邮件,发送成功或失败都进行相应的通知动作。
二、正式开始
1、配置
首先查看laravel配置文件config/queue.php,可以看到如下,sync表示会默认执行,非等待队列任务,如果使用队列任务必须要修改该值,并且.env文件中的配置也一定要改。
'default' => env('QUEUE_DRIVER', 'sync')
connections数组中可以看到很多直接的队列方式,database,redis,sqs等,有一些还需要安装拓展插件才能使用,我们这里就使用比较不费事的database作为实践,各默认配置含义如下
'database' => [ 'driver' => 'database', 'table' => 'jobs',//记录队列任务的表名 'queue' => 'default',//默认任务名 'retry_after' => 90,//任务在运行 90 秒后还未完成,那么将被释放回队列而不是删除掉。 ],
.evn中配置为database方式之后,我们需要创建几个队列任务所依赖的表,命令如下:
php artisan queue:table php artisan migrate
为了方便记录任务执行失败后的结果,我们把失败记录表也创建出来
php artisan queue:failed-table php artisan migrate
这几张表就是创建出来的table,数据库准备完毕后我们就可以对代码动手了。

2、代码开始
2.1首先我们需要创建任务类,可以直接通过artisan命令创建,也可以手动创建,命令如下
php artisan make:job TestQueue
会在app目录下看到产生一个Jobs目录以及TestQueue.php文件,代码编辑从这里开始
class TestQueue implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public $tries=3;//指定任务最大失败次数,级别高于启动的设置值 public $timeout=30;//任务最大的执行时间,级别高于启动设置值 protected $data;//任务传值 /** * 通常用于创建任务时的传值 * Create a new job instance. * @return void */ public function __construct($data) { $this->data=$data; } /** * 执行任务:去任务队列中获取任务,然后执行代码,执行完毕后删除队列中的任务 * Execute the job. * @return void */ public function handle() { DB::table('test')->insert($this->data); } /**任务失败时执行该方法 * @param Exception $e */ public function failed(Exception $e) { // 比如短信通知管理员或记录日志等 } }
2.2、创建控制器方法,实现队列
<?php namespace App\Http\Controllers; use App\Jobs\TestQueue; use Carbon\Carbon; use Illuminate\Support\Facades\Request; class SendController extends Controller{ /** * 当上面的任务类完成之后,我们就可以启动一个守护进程等待任务进入队列了 * php artisan queue:work 启动队列进程 * php artisan queue:restart 平滑重启 * php artisan queue:work --tries=3 指定失败次数,也可以在类中指定 * php artisan queue:work --timeout=30 队列任务执行的最大时间(秒) * php artisan queue:work --queue=name 指定该进程处理的队列名,只会处理该name的队列 * php artisan queue:work redis 指定驱动连接 * php artisan queue:work --sleep=3 我们可以使用 sleep 配置项来指定没有新的有效任务产生时的休眠时间 */ public function test_set(Request $request){ //给对应数据库中插入数据 $arr=[ 'name'=>substr(md5(time()),0,10), 'age'=>rand(10,100), 'tel'=>time() ]; $job=new TestQueue($arr);//最基本的任务创建,采用默认参数 $job=(new TestQueue($arr)) ->delay(Carbon::now()->addMinutes(1));//任务创建1分钟后执行,最多15分钟 $job=(new TestQueue($arr)) ->onQueue('name');//任务创建至指定队列,启动的进程也需要queue=name指定名字 $job=(new TestQueue($arr)) ->onConnection('sqs');//任务使用不同的驱动链接,当然可以指定任务连接和队列 dispatch($job); } }
最后我们要把守护进程启动,这才是执行队列任务的动作核心
php artisan queue:work
试着执行该路由方法后,查看数据库中就会有对应数据产生了,这就是最简单的队列任务,发短信、发邮件、发通知等实时性不要求很高的都可以采用队列任务实现。
你们的支持是我前进的动力,感谢来访!
解和