Laravel 队列使用的实现


Posted in PHP onJanuary 08, 2019

1 环境

Laravel是一种类似ThinkPHP的php框架,封装的诸多功能可以很方便的使用。队列Queue便是其中之一。

Windows环境下,可使用PHPstorm作为Laravel的集成开发环境IDE。

2 队列

Laravel可配置多种队列驱动,包括 "sync", "database", "beanstalkd", "sqs", "redis", "null"(具体参见app/config/queue.php)
其中sync为同步,database为使用数据库,后面三种为第三方队列服务,最后一种为不使用队列。

通过在 .env 中的 QUEUE_CONNECTION 选项,来决定选择何种驱动。

如 QUEUE_CONNECTION=database 即为选择数据库驱动队列。

3 原理

所谓队列,会有数据的生产者和消费者之分。生产者向队列中投递数据,消费者从队列中获取数据。

比如向用户发送邮件的场景:现在有10w封邮件需要发送,最简单的,我们需要有一个方法将邮件的收件人、内容等,拆分成10w条任务放在队列中,同时需要设置一个回调方法负责处理每条任务。当队列中有邮件发送任务时,队列会主动调用回调方法,并传递任务详情进去。回调方法处理完成后,单条邮件即发送完毕。其他邮件依样处理。

4 使用数据库驱动队列

4.1 生成任务表

在终端下输入

php artisan queue:table
php artisan migrate

在数据库连接正常的情况下,会在数据库中出现jobs表:

[id] bigint 
 [queue] nvarchar(255) 
 [payload] nvarchar(max) 
 [attempts] tinyint 
 [reserved_at] int 
 [available_at] int 
 [created_at] int

4.2 创建任务类

php artisan make:job SendEmail

在终端内执行上述命令,会自动生成 app/Jobs/SendMail.php 文件

class SendMail implements ShouldQueue

在该文件的handle方法中,可以放置任务处理逻辑。

4.3 发送任务

在任意位置,均可像下面一样调用 dispatch 发送任务

SendMail::dispatch($email);

4.4 驱动队列

完成上述步骤后,可以在数据库中发现一条记录(导出为insert SQL语句):

INSERT INTO [jobs]([id], [queue], [payload], [attempts], [reserved_at], [available_at], [created_at]) VALUES (6, N'default', N'{"displayName":"App\\Jobs\\ProcessPodcast","job":"Illuminate\\Queue\\CallQueuedHandler@call","maxTries":null,"timeout":null,"timeoutAt":null,"data":{"commandName":"App\\Jobs\\ProcessPodcast","command":"O:23:\"App\\Jobs\\ProcessPodcast\":8:{s:29:\"\u0000App\\Jobs\\ProcessPodcast\u0000data\";s:6:\"111222\";s:6:\"\u0000*\u0000job\";N;s:10:\"connection\";N;s:5:\"queue\";N;s:15:\"chainConnection\";N;s:10:\"chainQueue\";N;s:5:\"delay\";N;s:7:\"chained\";a:0:{}}"}}', 0, NULL, 1545980176, 1545980176);

此时任务已经放置在数据库内,只有将队列运行起来后,队列才能主动调用回调方法。

php artisan queue:work

在终端内运行上述命令即可。该命令还有诸多参数,如deamon、tries等,可根据需要指定。

4.5 守护进程

为了保证应用服务的稳定性,需要开启守护进程。

Linux下,一般使用 Supervisor ,Windows下使用 Forever

4.6 执行失败的处理

对于处理失败的任务,Laravel也提供的解决方案。通过运行如下命令,即可创建表以记录失败任务。

php artisan queue:failed-table
php artisan migrate

在数据库中即生成 failed_jobs :

[id] bigint
 [connection] nvarchar(max)
 [queue] nvarchar(max) 
 [payload] nvarchar(max) 
 [exception] nvarchar(max) 
 [failed_at] datetime

导致任务失败的 Exception 会被传递到 SendMail 的 failed 方法,因而你需要在SendMail中自行实现该方法,并做进一步处理。

任务执行失败的原因有很多,如传参错误、尝试次数超过限制、超时、甚至在 handle 方法中抛出异常,均会作为失败任务处理。

4.7 任务执行前后的处理

Laravel提供了任务执行前后的处理入口,即在 App/Providers/AppServiceProvider 中的 boot() 中加入如下代码:

public function boot()
{
   Queue::before( function (JobProcessing $event) {
     Log::info("处理任务前");
   });
   Queue::after( function (JobProcessed $event) {
     Log::info("处理任务后");
   });
}

传递的 $event 中,带有任务详情,几个简单的例子:

$event->connectionName
$event->job
$event->job->payload()

5 使用 Redis 驱动队列

5.1 Laravel 安装 Predis 包

在 Laravel 中使用 Redis 之前,需要通过 Composer 安装 predis/predis 包:

composer require predis/predis

上述拓展是帮助Laravel与Redis打交道的,我们现在还缺少Redis服务。

如果此时将 .env 中的 QUEUE_CONNECTION 改为 redis,访问时会报错:

Predis \ Connection \ ConnectionException (10061)
����Ŀ����������ܾ����޷����ӡ� [tcp://127.0.0.1:6379]

5.2 配置 Redis 服务

在Redis官网 下载源码后自行编译即可。

官方并未提供Windows版,Redis的Windows版式由微软工作组维护的,你可以从其GitHub页 找到。不过貌似已经不再维护了,最新的版本是16年发布的3.2.100。

Linux下通过简单的运行

./redis-server

即可开启服务,再通过

./redis-cli

来尝试使用Redis。使用也很简单,就是 set key value 和 get key。
Windows下安装后,在命令行中 cd 到安装目录

C:\Program Files\Redis>redis-server redis.windows.conf
C:\Program Files\Redis>netstat -an|find "6379"
 TCP  127.0.0.1:6379     0.0.0.0:0       LISTENING

即可开启Redis服务。

Redis服务的停止是通过如下命令:

C:\Program Files\Redis>redis-server --service-stop

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
php中使用DOM类读取XML文件的实现代码
Dec 14 PHP
比较详细PHP生成静态页面教程
Jan 10 PHP
php摘要生成函数(无乱码)
Feb 04 PHP
简单分析ucenter 会员同步登录通信原理
Aug 25 PHP
使用array_map简单搞定PHP删除文件、删除目录
Oct 29 PHP
PHP 快速排序算法详解
Nov 10 PHP
php返回字符串中所有单词的方法
Mar 09 PHP
PHP里的单例类写法实例
Jun 25 PHP
浅析PHP7新功能及语法变化总结
Jun 17 PHP
PHP编程实现多维数组按照某个键值排序的方法小结【2种方法】
Apr 27 PHP
PHP中实现中文字串截取无乱码的解决方法
May 29 PHP
php实现微信支付之退款功能
May 30 PHP
laravel 框架配置404等异常页面
Jan 07 #PHP
PHP array_shift()用法实例分析
Jan 07 #PHP
PHP parse_ini_file函数的应用与扩展操作示例
Jan 07 #PHP
PHP一个简单的无需刷新爬虫
Jan 05 #PHP
PHP智能识别收货地址信息实例
Jan 05 #PHP
PHP数字金额转换成中文大写显示
Jan 05 #PHP
PHP yield关键字功能与用法分析
Jan 03 #PHP
You might like
PHP中的异常处理机制深入讲解
2020/11/10 PHP
cookie丢失问题(认证失效) Authentication (用户验证信息)也会丢失
2009/06/04 Javascript
from 表单提交返回值用post或者是get方法实现
2013/08/21 Javascript
页面加载完毕后滚动条自动滚动一定位置
2014/02/20 Javascript
javascript生成随机大小写字母的方法
2014/02/20 Javascript
一个Action如何调用两个不同的方法
2014/05/22 Javascript
使用JQ来编写最基本的淡入淡出效果附演示动画
2014/10/31 Javascript
jQuery元素选择器用法实例
2014/12/23 Javascript
JavaScript统计字符串中每个字符出现次数完整实例
2016/01/28 Javascript
js 获取经纬度的实现方法
2016/06/20 Javascript
AngularJS  ng-table插件设置排序
2016/09/21 Javascript
node.js与C语言 实现遍历文件夹下最大的文件,并输出路径,大小
2017/01/20 Javascript
JavaScript实现星星等级评价功能
2017/03/22 Javascript
微信小程序http连接访问解决方案的示例
2018/11/05 Javascript
JavaScript私有变量实例详解
2019/01/24 Javascript
vue-cli webpack配置文件分析
2019/05/20 Javascript
ES10的13个新特性示例(小结)
2019/09/23 Javascript
vue 数据遍历筛选 过滤 排序的应用操作
2020/11/17 Javascript
理解Python中的类与实例
2015/04/27 Python
pandas中的DataFrame按指定顺序输出所有列的方法
2018/04/10 Python
python3.4实现邮件发送功能
2018/05/28 Python
使用Python操作FTP实现上传和下载的方法
2019/04/01 Python
树莓派安装OpenCV3完整过程的实现
2019/10/10 Python
CentOS7下安装python3.6.8的教程详解
2020/01/03 Python
使用 pytorch 创建神经网络拟合sin函数的实现
2020/02/24 Python
Pycharm安装第三方库失败解决方案
2020/11/17 Python
CSS3移动端vw+rem不依赖JS实现响应式布局的方法
2019/01/23 HTML / CSS
美国男士和女士奢侈品折扣手表购物网站:Certified Watch Store
2018/06/13 全球购物
NBA欧洲商店(英国):NBA Europe Store UK
2018/07/27 全球购物
世界上最大的铁人三项商店:Tri UK
2020/11/04 全球购物
商场主管竞聘书
2014/03/31 职场文书
国家奖学金获奖感言
2014/08/16 职场文书
安全标兵事迹材料
2014/08/17 职场文书
十一国庆节“向国旗敬礼”主题班会活动方案
2014/09/27 职场文书
Html5大屏数据可视化开发的实现
2021/06/11 HTML / CSS
Redis唯一ID生成器的实现
2022/07/07 Redis