消费信息如下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消息队列的更多相关文章

  1. 进程间通信系列 之 消息队列函数(msgget、msgctl、msgsnd、msgrcv)及其范例

    进程间通信系列 之 概述与对比   http://blog.csdn.net/younger_china/article/details/15808685  进程间通信系列 之 共享内存及其实例   ...

  2. php消息队列之 think queue消息队列初体验

    使用thinkphp 5的  消息队列 think queue ● php think queue:listen --queue queuename ● php think queue:work -- ...

  3. think queue 消息队列初体验

    使用的是tp5  自带的消息队列 thinkphp top里的 消息队列框架 think-queue 这是thinkphp官方团队开发的一个专门支持队列服务的扩展包 消息队列应用场景: 消息队列适用于 ...

  4. [2017-10-25]Abp系列——集成消息队列功能(基于Rebus.Rabbitmq)

    本系列目录:Abp介绍和经验分享-目录 前言 由于提交给ABP作者的集成消息队列机制的PR还未Review完成,本篇以Abplus中的代码为基准来介绍ABP集成消息队列机制的方案. Why 为什么需要 ...

  5. Redis系列(三)--消息队列、排行榜等

    Redis命令执行生命周期: 发送命令--->排队(单线程)--->执行命令--->返回结果 慢查询: 只是针对命令执行阶段 慢查询日志通过一个固定长度的FIFO queue,这个q ...

  6. C++ message queue 消息队列入门

    说明:当我们有多个线程以不同的速度运行并且我们想要以特定的顺序从一个线程向另一个线程发送信息时,消息队列可能会有用. 这个想法是,发送线程将消息推送到队列中,而接收线程将消息按自己的步调弹出. 只要发 ...

  7. queue消息队列

    class queue.Queue(maxsize=0) #先入先出 class queue.LifoQueue(maxsize=0) #last in fisrt out  class queue. ...

  8. Python中queue消息队列模块

    from queue import Queue from queue import PriorityQueue print("Queue类实现了一个基本的先进先出(FIFO)容器,使用put ...

  9. RabbitMQ消息队列系列教程(一)认识RabbitMQ

    摘要 RabbitMQ是最为流行的消息中间件,是处理高并发业务的利器.本系列教程,将跟大家一起学习RabbitMQ. 目录 RabbitMQ是什么? RabbitMQ的特点是什么? 一.RabbitM ...

  10. C# Queue与RabbitMQ的爱恨情仇(文末附源码):Q与MQ消息队列简单应用(二)

    上一章我们讲了队列( Queue),这一章我们讲Message Queue消息队列,简称MQ. 定义: MQ是MessageQueue,消息队列的简称(是流行的开源消息队列系统,利用erlang语言开 ...

随机推荐

  1. 超详细!深入分析PPTP虚拟专用网搭建与抓包

    PPTP虚拟专用网搭建与抓包分析实验 实验目的:掌握PPP协议VPN的搭建,通过分析pptp建立,理解chap连接建立的过程 实验过程: 环境搭建 Windows 11系统 VMware虚拟机.kal ...

  2. 微信公众号,微信小程序,百度小程序免费发放了

    小程序免费领取了,是真的免费哦 每人限领一套,100%开源,无后门 免费领取方式直接看tpframe官方网站

  3. MyBatis反射模块源码分析

    说明:本文参考至https://www.jianshu.com/p/baba62bbc107 MyBatis 在进行参数处理.结果映射时等操作时,会涉及大量的反射操作.为了简化这些反射相关操作,MyB ...

  4. 部署Zabbix

    https://blog.csdn.net/qq_57414752/article/details/125819822

  5. mediaserverd

    1.mediaserverd是什么 mediaserverd(/usr/sbin/mediaserverd)是被root进程launchd启动的一个后台(daemon)进程,其描述文件为com.app ...

  6. 一个前后端都有的后台管理系统,使用nest.js和vue3

    今天介绍一个新的Vue后台管理框架,相比其他后台功能丰富管理系统,这个后台管理系统可以用干净简洁来形容--Nova-admin Nova-admin Nova-admin 是一个基于Vue3.Vite ...

  7. Vue.js 动态组件与异步组件

    title: Vue.js 动态组件与异步组件 date: 2024/6/2 下午9:08:50 updated: 2024/6/2 下午9:08:50 categories: 前端开发 tags: ...

  8. js 判断手机号格式

    大江东去,浪淘尽,千古风流人物.故垒西边,人道是,三国周郎赤壁.乱石穿空,惊涛拍岸,卷起千堆雪.江山如画,一时多少豪杰.遥想公瑾当年,小乔初嫁了,雄姿英发.羽扇纶巾,谈笑间,樯橹灰飞烟灭.故国神游,多 ...

  9. LeetCode 451. Sort Characters By Frequency 根据字符出现频率排序 (C++/Java)

    题目: Given a string, sort it in decreasing order based on the frequency of characters. Example 1: Inp ...

  10. The bean ‘xxx‘ could not be injected as a ‘xxx‘because it is a JDK dynamic proxy that implements错误解决

    1.解决方法:使用@Autowired 2.@autowired和@resource注解的区别区别:1.@Autowired注解由Spring提供,只按照byType注入:@resource注解由J2 ...