在Web开发中,我们经常会遇到需要批量处理任务的场景,比如群发邮件、秒杀资格获取等,我们将这些耗时或者高并发的操作放到队列中异步执行可以有效缓解系统压力、提高系统响应速度和负载能力。实现队列有多种方式,Laravel也支持多种队列实现驱动,比如数据库、Redis、Beanstalkd、IronMQ及Amazon SQS等,此外还支持同步方式实现队列(默认),甚至将队列驱动设置为null表示不使用队列。Laravel为这些队列驱动提供了统一的接口,从而方便我们任意切换驱动而不需要改变业务逻辑编码,提供代码复用性。
以下介绍使用数据库作为驱动,实现发送邮件队列实例:
首先,修改环境配置文件.env,将队列驱动改为数据库;
QUEUE_DRIVER=database
然后,创建一个用于存放队列的表jobs,执行以下两条命令后,会在默认的数据库自动创建一个jobs表;
php artisan queue:table
php artisan migrate
生成一个任务类,该类作为执行邮件队列的接受和发送处理;
php artisan make:job SendMail
执行完命令后,app/Jobs会自动创建,并在Jobs目录下创建了SendMail.php,接下来,就可以在该类的handle方法里面处理接受邮件队列和发送任务了;
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 Illuminate\Support\Facades\Mail; class SendMail implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; protected $tries = 5;//失败尝试次数 protected $timeout = 120;//脚本执行超时时间 protected $data = []; /** * Create a new job instance. * @return void */ public function __construct($data){ $this->data = $data; } /** * Execute the job. * @return void */ public function handle(){ set_time_limit(0); $data = $this->data; Mail::send('mailtemp.taskmail', $data, function($message) use($data) { $message->to($data['emails'])->subject($data['title']); }); info('-------------------执行邮件队列-----------------'); } }
接下来,就可以在任意一个地方,调用该类,把邮件放入该队列里面;
$data['emails'] = ['test@qq.com']; $data['title'] = "test"; $data['msg']="test"; $job = new SendMail($data); $job->onConnection("database")->onQueue('SendMail'); return dispatch($job);
此时,还不能执行邮件发送,需要在laravel项目根目录启用该队列的服务;
php artisan queue:work database --queue=SendMail
注意,如果关闭了命令窗口,该服务会自动停止,所以,需要让服务在后台执行;
nohup php artisan queue:work database --queue=SendMail &
用nohup运行命令可以使命令永久的执行下去,注意了nohup没有后台运行的意思,&才是后台运行,使用
nohup COMMAND &
就是使命令永久的在后台执行,nohup执行后,会产生日志文件,把命令的执行中的消息保存到这个文件中,一般在当前目录下,如果当前目录不可写,那么自动保存到执行这个命令的用户的home目录下,完整的执行命令是;
nohup php artisan queue:work database --queue=SendMail > SendMail.log 2>&1 &
如果修改了队列类SendMail,需要重启才能生效;
php artisan queue:restart
自此,完成了整个实例,当然还有延时执行、任务优先级、失败任务等处理,官网都有详细介绍,这里就不一一赘述;
题外话:
运行队列监听器
在浏览器中访问http://laravel.cn/mail/addEmail/,此时任务被推送到Database队列中,我们还需要在命令行中运行Artisan命令执行队列中的任务。Laravel为此提供了三种Artisan命令:
queue:work 默认只执行一次队列请求, 当请求执行完成后就终止; queue:listen 监听队列请求,只要运行着,就能一直接受请求,除非手动终止; queue:work --daemon 同 listen 一样, 只要运行着,就能一直接受请求,不一样的地方是在这个运行模式下,当新的请求到来的时候,不重新加载整个框架,而是直接 fire 动作。能看出来, queue:work --daemon 是最高级的,一般推荐使用这个来处理队列监听。
注:使用 queue:work –daemon ,当更新代码的时候,需要停止,然后重新启动,这样才能把修改的代码应用上。
所以我们接下来在命令行中运行如下命令:
php artisan queue:work --daemon
转载请注明:永盟博客 » laravel队列应用