TP5系列 | Queue消息队列
消费信息如下ThinkPHP5 Queue消息队列
优点
1、Queue内置了 Redis,Database,Topthink ,Sync这四种驱动,本文使用Redis驱动
2、Queue消息队列适用于大并发或者返回结果 时间有点长并需要批量操作的第三方接口,可用于短信发送、邮件发送、APP推送
3、Queue消息消息可进行发布,获取,执行,删除,重发,失败处理,延迟执行,超时控制等操作
流程图
创建队列
文件路径:application\common\queue\TestQueue.php
TestQueue.php
参考代码
<?php
namespace app\common\queue; use think\facade\Log;
use think\queue\Job; class TestQueue
{
public function fire(Job $job, $data)
{
$isJobDone = $this->testJob($data);
// 如果任务执行成功后 记得删除任务,不然这个任务会重复执行,直到达到最大重试次数后失败后,执行failed方法
if ($isJobDone) {
$job->delete();
} else {
//通过这个方法可以检查这个任务已经重试了几次了
$attempts = $job->attempts();
echo $attempts;
if ($attempts == 0 || $attempts == 1) {
// 重新发布这个任务
$job->release(2); //$delay为延迟时间,延迟2S后继续执行
} elseif ($attempts == 2) {
$job->release(5); // 延迟5S后继续执行
}
}
} /**
* @Desc: 任务执行失败后自动执行方法
* @param $data
*/
public function failed($data)
{
// ...任务达到最大重试次数后,失败了
Log::error('任务达到最大重试次数后,失败了 '.json_encode($data));
} /**
* @Desc: 自定义需要加入的队列任务
*/
private function testJob($data)
{
$jsonData = json_encode($data);
echo "1、具体执行任务接受到的参数:{$jsonData} \r\n";
if($data){
echo "2、恭喜你!{$data['email']} 邮件发送成功了 \r\n";
return true;
}else{
echo "2、很遗憾,{$data['email']} 邮件发送失败了 \r\n";
return false;
}
}
}
配置队列
1、这里使用Redis驱动来存储队列消息
2、队列配置文件路径:application\config\queue
配置参考代码
return [
'connector' => 'Redis',
'expire' => 3600,
'default' => 'REDIS_QUEUE',
'host' => 'dnmp-redis',
'port' => 6379,
'password' => '',
'select' => 0,
'timeout' => 0,
'persistent' => false,
];
生产者参考代码
/**
* @Desc: 生产者生产消息
*/
public function productMsg()
{
// 当前任务所需的业务数据,不能为 resource 类型,其他类型最终将转化为json形式的字符串
$data = [
'email' => rand(11,99).'@qq.com',
'username' => 'Tinywan'
]; // 当前任务归属的队列名称,如果为新队列,会自动创建
$queueName = 'testQueue'; // 将该任务推送到消息队列,等待对应的消费者去执行
$isPushed = Queue::push(TestQueue::class, $data, $queueName); // database 驱动时,返回值为 1|false; redis驱动时,返回值为 随机字符串|false
if ($isPushed !== false) {
echo '['.$data['email'].']'." 队列加入成功 \r\n";
} else {
echo "队列加入失败 \r\n";
}
}
为了方便演示,这里使用cli模式。
执行生产者:php product_msg.php
# php product_msg.php
[27@qq.com] 队列加入成功
# php product_msg.php
[77@qq.com] 队列加入成功
1、这时候消息已经被持久化到Redis中去了(通过列表去存储)
2、推送成功,虽然我们这时候已经写好了消费者,但是我们并没有开始消费。但是推送消息依然是成功的。这个就是中间件的优势。他连接两个系统,但是又不会互相耦合,生产者并不会因为消费者的异常而影响到自己。
3、消息推送成功之后,如果没有消费者,消息会堆积在队列中。不过别怕,消息堆积很正常,并且一般的中间件堆积能力是非常强的。比如阿里就宣传自己mq可以堆积上亿条数据。
查看Redis消息与队列
> docker exec -it dnmp-redis redis-cli
127.0.0.1:6379> keys *
127.0.0.1:6379> keys *
1) "queues:testQueue"
127.0.0.1:6379> TYPE queues:testQueue
list
127.0.0.1:6379> LRANGE queues:testQueue 0 -1
1) "{\"job\":\"app\\\\common\\\\queue\\\\TestQueue\",\"data\":{\"email\":\"27@qq.com\",\"username\":\"Tinywan\"},\"id\":\"MLgNb4LFALhtmp7HZtfXMFPRUT0r94Bi\",\"attempts\":1}"
2) "{\"job\":\"app\\\\common\\\\queue\\\\TestQueue\",\"data\":{\"email\":\"77@qq.com\",\"username\":\"Tinywan\"},\"id\":\"JM16vvjMylfJDnOpldJaHda8xMwuYYzP\",\"attempts\":1}"
127.0.0.1:6379>
消费者
开始消费消息。执行cli 命令
php think queue:work--queue队列名称
# php think queue:work --queue testQueue
1、具体执行任务接受到的参数: {"email":"27@qq.com","username":"Tinywan"}
2、恭喜你!27@qq.com 邮件发送成功了
Processed: app\common\queue\TestQueue
这里每消费掉一条消息,Redis数据库中将会减少一条消息
查看Redis队列消息
127.0.0.1:6379> LRANGE queues:testQueue 0 -1
1) "{\"job\":\"app\\\\common\\\\queue\\\\TestQueue\",\"data\":{\"email\":\"77@qq.com\",\"username\":\"Tinywan\"},\"id\":\"JM16vvjMylfJDnOpldJaHda8xMwuYYzP\",\"attempts\":1}"
127.0.0.1:6379>命令行挂起守护进程执行
/usr/bin/php /var/www/tp5/think queue:work --daemon --queue testQueue --memory 256
--daemon 是否循环执行,如果不加该参数则该命令处理完下一个消息就退出 --queue 要处理的队列的名称 --delay 0 如果本次任务执行抛出异常且任务未被删除时,设置其下次执行前延迟多少秒,默认为0。 --memory 该进程允许使用的内存上限,以M为单位。
流程图
消费信息如下
php think queue:work --daemon --queue testQueue
1、具体执行任务接受到的参数: {"email":"77@qq.com","username":"Tinywan"}
2、恭喜你!77@qq.com 邮件发送成功了
Processed: app\common\queue\TestQueue
1、具体执行任务接受到的参数: {"email":"80@qq.com","username":"Tinywan"}
2、恭喜你!80@qq.com 邮件发送成功了
Processed: app\common\queue\TestQueue
1、具体执行任务接受到的参数: {"email":"34@qq.com","username":"Tinywan"}
2、恭喜你!34@qq.com 邮件发送成功了
Processed: app\common\queue\TestQueue
1、命令行模式可以常驻内存不停的执行php代码。这样就可以达到类似于静态语言的java的效果。
2、一开始监听队列。刚刚在队列中堆积的消息立刻就被获取到,开始执行了代码。最后执行完成,删除了消息。
3、在 queue:work--daemon
单进程循环消费的时候,改了代码是不会生效的。这时脚本语言有点类似于静态语言在执行。所以需要我们用 queue:restart
重启 work 进程 。
命令行挂起守护进程执行
/usr/local/php/bin/php /data/wwwroot/default/thinkphp_5/think queue:work --daemon --queue testQueue --memory 256
查看进程是否在运行
# ps
PID USER TIME COMMAND
1 root 0:00 php-fpm: master process (/usr/local/etc/php-fpm.conf)
6 www-data 0:00 php-fpm: pool www
7 www-data 0:00 php-fpm: pool www
16 root 0:00 sh
56 root 0:00 sh
113 root 0:00 php think queue:work --daemon --queue testQueue
你再也不用守在终端了,以后只负责生产消息就可以了。Redis队列也不会积累消息了
其他(中间件)
中间件系统的定义是两个独立的不同的系统在中间构建起传递消息的工具。但是同一个系统也可以通过中间件来榨取性能,大家肯定项目中遇到过性能瓶颈。
比如发送邮件,发送短信,转换视频格式等等。这些业务都是比较耗性能,又对先后顺序不敏感的业务。这种业务就非常适合使用消息队列系统来异步处理,使性能提升。
重启队列和生成队列
TP5系列 | Queue消息队列的更多相关文章
- 进程间通信系列 之 消息队列函数(msgget、msgctl、msgsnd、msgrcv)及其范例
进程间通信系列 之 概述与对比 http://blog.csdn.net/younger_china/article/details/15808685 进程间通信系列 之 共享内存及其实例 ...
- php消息队列之 think queue消息队列初体验
使用thinkphp 5的 消息队列 think queue ● php think queue:listen --queue queuename ● php think queue:work -- ...
- think queue 消息队列初体验
使用的是tp5 自带的消息队列 thinkphp top里的 消息队列框架 think-queue 这是thinkphp官方团队开发的一个专门支持队列服务的扩展包 消息队列应用场景: 消息队列适用于 ...
- [2017-10-25]Abp系列——集成消息队列功能(基于Rebus.Rabbitmq)
本系列目录:Abp介绍和经验分享-目录 前言 由于提交给ABP作者的集成消息队列机制的PR还未Review完成,本篇以Abplus中的代码为基准来介绍ABP集成消息队列机制的方案. Why 为什么需要 ...
- Redis系列(三)--消息队列、排行榜等
Redis命令执行生命周期: 发送命令--->排队(单线程)--->执行命令--->返回结果 慢查询: 只是针对命令执行阶段 慢查询日志通过一个固定长度的FIFO queue,这个q ...
- C++ message queue 消息队列入门
说明:当我们有多个线程以不同的速度运行并且我们想要以特定的顺序从一个线程向另一个线程发送信息时,消息队列可能会有用. 这个想法是,发送线程将消息推送到队列中,而接收线程将消息按自己的步调弹出. 只要发 ...
- queue消息队列
class queue.Queue(maxsize=0) #先入先出 class queue.LifoQueue(maxsize=0) #last in fisrt out class queue. ...
- Python中queue消息队列模块
from queue import Queue from queue import PriorityQueue print("Queue类实现了一个基本的先进先出(FIFO)容器,使用put ...
- RabbitMQ消息队列系列教程(一)认识RabbitMQ
摘要 RabbitMQ是最为流行的消息中间件,是处理高并发业务的利器.本系列教程,将跟大家一起学习RabbitMQ. 目录 RabbitMQ是什么? RabbitMQ的特点是什么? 一.RabbitM ...
- C# Queue与RabbitMQ的爱恨情仇(文末附源码):Q与MQ消息队列简单应用(二)
上一章我们讲了队列( Queue),这一章我们讲Message Queue消息队列,简称MQ. 定义: MQ是MessageQueue,消息队列的简称(是流行的开源消息队列系统,利用erlang语言开 ...
随机推荐
- nginx相关报错
# openresty -s reloadnginx: [warn] conflicting server name "community-gw.xxx.cn" on 0.0.0. ...
- 基于Python实现MapReduce
一.什么是MapReduce 首先,将这个单词分解为Map.Reduce. Map阶段:在这个阶段,输入数据集被分割成小块,并由多个Map任务处理.每个Map任务将输入数据映射为一系列(key, va ...
- powershell 设置代理
$env:HTTP_PROXY="http://127.0.0.1:10809" $env:HTTPS_PROXY="http://127.0.0.1:10809&quo ...
- Python依据遥感影像的分幅筛选出对应的栅格文件
本文介绍基于Python语言,结合已知研究区域中所覆盖的全部遥感影像的分幅条带号,从大量的遥感影像文件中筛选落在这一研究区域中的遥感影像文件的方法. 首先,先来明确一下本文所需实现的需求.现已 ...
- bpmnjs
在 bpmn.js 中,`bpmnModeler.get()` 方法用于获取不同的模块,你可以通过这些模块来访问和操作 BPMN 模型的不同部分.以下是一些常用的模块和对应的用途: 1. **Canv ...
- xv6 的锁机制
LOCK 公众号:Rand_cs 锁,大家应该很熟悉了,用来避免竞争,实现同步.本文以 xv6 为例来讲解锁本身是怎么实现的,废话不多说,先来看一些需要了解的概念: 一些概念 公共资源:顾名思义就是被 ...
- 错误 CS1617 Invalid option '7.3' for /langversion; must be ISO-1, ISO-2, Default or an integer in range 1 to 6.
严重性 代码 说明 项目 文件 行 禁止显示状态错误 CS1617 Invalid option '7.3' for /langversion; must be ISO-1, ISO-2, Defau ...
- cent os docker yum源
国外镜像一般很难访问,建议配置阿里云镜像.yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/ ...
- LocalDateTime日期格式化和指定日期的时分秒
LocalDateTime日期格式化和指定日期的时分秒 package com.example.core.mydemo.date; import java.time.LocalDate; import ...
- mysql 查询差集方法
第一种是通过not in的方式去处理: select id from table_a where id not in (select id from table_b); 第二种则是通过左连接(left ...