本篇文章是针对thinkPHP6.0的消息队列的一个讲解,可能部分人没有测试的使用场景,这里我给大家创造了一个。
> 使用场景:通过消息队列采集远程图片到本地服务器。 要求不占用服务器资源太高,可以随时添加,随时采集。
其实上述的场景,也就是吧发送邮件[通知]改成采集图片了。
下面教程开始:
1:下载composer包文件到你的项目
```
https://packagist.org/packages/topthink/think-queue
composer require topthink/think-queue
```
2:修改配置项
```
'default'=>'sync' //驱动类型,可选择 sync(默认):同步执行,database:数据库驱动,redis:Redis驱动//或其他自定义的完整的类名
]
```
注意:配置文件位于 config/queue.php 很多人项目下面是没有的,大家可以参考我给的目录复制项目的配置代码
[![](https://cdn.micuer.com/data/upload/20201029/5f9a7a92d303c.png)](https://cdn.micuer.com/data/upload/20201029/5f9a7a92d303c.png)
```
// +----------------------------------------------------------------------
// | 应用设置
// +----------------------------------------------------------------------
return [
'default' => 'redis', //需要你自己修改
'connections' => [
'sync' => [
'type' => 'sync',
],
'database' => [
'type' => 'database',
'queue' => 'default',
'table' => 'jobs',
'connection' => null,
],
'redis' => [
'type' => 'redis',
'queue' => 'default',
'host' => '127.0.0.1',
'port' => 6379,
'password' => 'xxxxxxx',//需要你自己修改
'select' => 0,
'timeout' => 0,
'persistent' => false,
],
],
'failed' => [
'type' => 'none',
'table' => 'failed_jobs',
],
];
```
3:创建任务类【消费者】
> 单模块项目推荐使用 app\job 作为任务类的命名空间 多模块项目可用使用 app\module\job 作为任务类的命名空间 也可以放在任意可以自动加载到的地方
任务类不需继承任何类,如果这个类只有一个任务,那么就只需要提供一个fire方法就可以了,如果有多个小任务,就写多个方法,下面发布任务的时候会有区别
每个方法会传入两个参数 think\queue\Job $job(当前的任务对象) 和 $data(发布任务时自定义的数据)
还有个可选的任务失败执行的方法 failed 传入的参数为$data(发布任务时自定义的数据)
大家仔细理解下这段话吧,不理解也无所谓,当最后你的demo成功后你就会 恍然大悟
我的代码如下
```
namespace app\job;
use think\queue\Job;
/**
* Class Job1
* @package app\job
* 测试用 qq571031767 远程下载图片
*/
class Job1{
public function fire(Job $job, $data){
//....这里执行具体的任务
$content = file_get_contents($data);
$time = time();
$res = file_put_contents("./dd/{$time}.png",$content);
if ($job->attempts() > 3) {
//通过这个方法可以检查这个任务已经重试了几次了
$res = file_put_contents("./dd/{$time}.txt","任务执行次数太多,失败");
}
//如果任务执行成功后 记得删除任务,不然这个任务会重复执行,直到达到最大重试次数后失败后,执行failed方法
$job->delete();
// 也可以重新发布这个任务
//$job->release(3); //$delay为延迟时间
}
public function failed($data){
// ...任务达到最大重试次数后,失败了
}
}
```
目录如下
[![](https://cdn.micuer.com/data/upload/20201029/5f9a7b75e73bc.png)](https://cdn.micuer.com/data/upload/20201029/5f9a7b75e73bc.png)
4:异步添加任务
> 比如:你突然发现一张好好看的图片,需要采集,是不是应该将这个任务添加到队列中【一般这一步都是人为触发】,这里就用刷新网页来模拟认为触发场景
代码如下
```
public function test()
{
p("消息队列生产者-生产了一条任务时间:".date("Y-m-d H:i:s"));
$job = 'app\job\Job1';
$res = Queue::push($job, $data = 'https://www.qudonghao.cn//uploads/20201028/4469ef0830816c8e75bf76a8466280ce.png', $queue = null);
p($res."-res");
}
```
5:以上代码全部准备完毕之后,就需要再服务器开启任务队列的监听了
以下选择1行命令即可
```
php think queue:listen
php think queue:work
```
6:成果展示
[![](https://cdn.micuer.com/data/upload/20201029/5f9a7cd3163fb.png)](https://cdn.micuer.com/data/upload/20201029/5f9a7cd3163fb.png)
------------
[![](https://cdn.micuer.com/data/upload/20201029/5f9a7cf29b2f2.png)](https://cdn.micuer.com/data/upload/20201029/5f9a7cf29b2f2.png)
可见我手动刷新了2次,队列也自动执行了2次并且采集到了我想要的图片。大家按照我的代码将流程走一遍,也就能清除的理解 消息队列
下面是消息队列的一些理论性的文字介绍
消息队列中间件是分布式系统中重要的组件,主要解决应用耦合、异步消息、流量削锋等问题。实现高性能、高可用、可伸缩和最终一致性架构。是大型分布式系统不可缺少的中间件。
> 场景说明:用户注册后,需要发送注册邮件和发送注册信息,传统的做法有两种:串行方式、并行方式
不复制了,建议去这里看吧
https://www.jianshu.com/p/689ce4205021