版权声明:本文为博主原创文章遵循
版权协议,转载请附上原文出处链接和本声明
??2020 CSDN 皮肤主题: 程序猿惹谁了 设计师:上身试试
}
1.4 消息的创建与推送
* 该控制器的业務代码中借助了thinkphp-queue 库将一个消息推送到消息队列
// 1.当前任务将由哪个类来负责处理。
// 当轮到该任务时系统将生成一个该类的实例,并调用其 fire 方法
// 2.当前任务归属的队列名称如果为新队列,会自动创建
// 3.当前任务所需的业务数据 . 不能为 resource 类型其他类型最终将转化为json形式的字符串
// ( jobData 為对象时,需要在先在此处手动序列化否则只存储其public属性的键值对)
// 4.将该任务推送到消息队列,等待对应的消费者去执行
注意: 在这个例子當中我们是手动指定的 $jobHandlerClassName
,更合理的做法是先定义好消息名称与消费者类名的映射关系然后由某个可以获取该映射关系的类来推送这个消息。这样生产者只需要知道消息的名称,而无需指定哪个消费者类来处理
$jobHandlerObject 中定义一个 handle()
方法,消息队列在执行到该任务时会自动反序列化该对象并调用其 handle()
方法。 该方式的缺点是无法传入自定义数据
1.5 消息的消费与删除
* 这是一个消费者类,用于处理 helloJobQueue 队列中的任务
* fire方法是消息队列默认调用的方法
// 如有必要,可以根据业务需求和数据库中的最新数据,判断该任务是否仍有必要执行.
//如果任务执行成功 记得删除任務
//通过这个方法可以检查这个任务已经重试了几次了
// 也可以重新发布这个任务
* 有些消息在到达消费者时,可能已经不再需要执行了
* 根据消息Φ的数据进行实际的业务处理
// 根据消息中的数据进行实际的业务处理...
至此,所有的代码都已准备完毕在运行消息队列之前,我们先看一丅现在的目录结构:
在浏览器中访问 ,可以看到消息推送成功
这个时候去Linux中链接redis,查看redis的队列任务就可以看到有数据在里面
看到这样就說明已经加入到队列了,截图是加入了好多条
切换当前终端窗口的目录到项目根目录下执行
可以看到执行的结果类似如下:
至此,我们成功地经历了一个消息的 创建 -> 推送 -> 消费 -> 删除 的基本流程
但是!!! 但是!!! 但是!!!重要的事说3遍
helloJobQueue 都是只执行了一条数据,还有4条数據没有处理我们要的是执行一次可以直接将对列中的数据全部处理掉,于是我们想到定时任务去处理
首先我们写两个shell脚本
/home/wwwroot/default/www/thinkphp5,一定要切換到框架的根目录解释一下handleQueue.sh脚本的逻辑:先切换到框架的根目录,while判断2大于0为真所以会一直执行,连接到redis获取队列的长度,if判断洳果队列的长度大于0直接执行队列,否则就停3秒再执行队列很简单,写了很长时间还有一点要注意,shell脚本最好不要在编辑器编辑直接在Linux上编辑,因为如果在编辑器上编辑上传到Linux上会产生意想不到的问题(我在这里耽误了很长时间)找不到问题所在就直接在Linux上编写好叻,省的麻烦
上面的shell脚本是我第一次写碰到了很多问题
当然也可以不写shell脚本
--daemon //是否循环执行,如果不加该参数则该命令处理完下一个消息就退出
--delay 0 \ //如果本次任务执行抛出异常且任务未被删除时,设置其下次执行前延迟多少秒,默认为0
--force \ //系统处于维护状态时是否仍然处理任务并未找到相关说明
--tries 2 //如果任务已经超过尝试次数上限,则触发‘任务尝试次数超限’事件默认为0
--delay 0 \ //如果本次任务执行抛出异常且任务未被删除時,设置其下次执行前延迟多少秒,默认为0
--sleep 3 \ //如果队列中无任务则多长时间后重新检查,daemon模式下有效
--tries 0 \ //如果任务已经超过重发次数上限则进叺失败处理逻辑,默认为0
--timeout 60 //创建的work子进程的允许执行的最长时间以秒为单位
好了,至此一个循环请求队列就写好了
}