之前群里很多会员说如何用 yii2 实现队列功能, 这个系列我们就来说说 yii2 官方的队列扩展 yii2-queue, 细节很多, 第一篇通过一个例子带你入门
先说需求吧~
我想做这样一个功能: 每次有新视频发布的时候, 给订阅过此视频所在教程的会员发送一条模板消息, 但是我如果在发布课程的时候就一次性发送模板消息有可能导致速度问题和被封的危险
所以我想将接收者们在时间上分开, 比如 100 个人, 每 5-10 秒发送一个, 我用 yii2-queue 来实现它
yii2-queue 是 yii2 官方去年推出的一个扩展, 支持延迟推送并且队列可以存储到多种媒介中, 比如文件数据库等等
在队列中有几个概念要先说下
任务 (task)
就是我们具体要做的事情, 在本次就是发送微信模板消息这样一件事情, yii2-queue 说每个任务都应该被定义为一个单独的类任务最终会进入到队列中等待发送
工作者 (worker)
工作者负责任务的调度, 比如当下一秒应该执行队列中的哪个任务了, 当然它还负责监听一些信息, 比如当前队列有多少个任务在等待多少个已经完成等
因此我的思路来了, 在新建视频的时候我将要发送的模板消息放到队列中, 这个过程并不负责发送, 然后有一个命令行 worker 帮我完成具体发送工作
先配置
在 yii2 中 yii2-queue 是以组件的形式存在, 我们先来安装它
composer require yiisoft / yii2 - queue
安装后你可以在 vendor 的 yiisoft 里找到它, 然后还需要简单的配置
// config/web.php
return [
'bootstrap' => [
'queue',
],
'components' => [
'queue' => [
'class' => \yii\queue\file\Queue::class,
],
],
];
我们将 queue 加到预加载属性 bootstrap 中, 这样 worker 就可以在命令行调用了, 接下来配置 queue 组件, 我们这里指定的是 \ yii\queue\file\Queue::class, 就是用文件存放队列信息
配置好 queue 的组件属性后, 在代码中就可以用 Yii::$app->queue 来执行队列的相关功能
构造任务类
既然 yii2 推荐将每个任务做成一个类, 那就弄吧, yii2-queue 的要求不高, 你只要让这个类实现 \yii\queue\JobInterface 接口就可以了
namespace app\queue;
class TemplateJob extends Component implements\yii\queue\JobInterface {...
/**
* 视频订阅 ID
* @var
*/
public $subscribeId;
/**
* 执行队列任务
* @param \yii\queue\Queue $queue
* @return boolean
*/
public
function execute($queue) {
$subscribe = Subscribe: :findOne($this - >subscribeId);
}
}
代码思路如上面一样, 其中 execute 是我们对接口 JobInterface 的实现, 它负责具体的发送工作 (任务的逻辑), 而我让 TemplateJob 继承于 Component 的目的是为了方便接下来推送任务到队列方便
记住上面的代码和你疑惑的地方, 我们往下看
开始推送
有了任务类, 我们只需要在相关代码中实现推送, 这些模板发送任务就可以到队列中了
// 某一段代码
$total = 0;
foreach($subscribes as $subscribe){
...
Yii::$app->queue->delay(rand(5,10)*$total)->push(new TemplateJob([
'subscribeId'=>$subscribe->id
]));
$total++;
}
上面代码将具体的一个一个的任务推送到了队列中, 因为我们的 TemplateJob 继承于 yii2 的 Component, 所以实例化一个 TemplateJob 对象时候传递的参数会被分配到对应的 TemplateJob 类对象的属性上, 也就是 xxx->subscribeId = $subscribe->id
然后用 yii2-queue 给我们提供的 push 功能就可以推送了, 如果我们不设置任务限制时间, 当队列的 worker 发现有任务就会直接发送, 但是我希望将时间分散开, 因此我是用了组件的 delay 方法, 它可以设置一个延迟时间, 我是在 5-10 秒间取一个数字, 然后乘以这个任务的排号, 这里我单独使用了 $total 而不是 foreach 的 $key 的原因是并不是所有的 $subscribe 都会推送
记住, delay 很有用
现在一个一个任务就在队列中了, 生产线即将启动, 我们的机器手 worker 即将完成调度工作
辛苦的 worker
上面我们讲了在队列中有一个很重要的概念叫做工作者 (worker), 它负责队列的任务执行工作
在 yii2-queue 中有几种方法都可以实现 worker 自动执行功能, 我们先来熟悉一种 SupervisorSupervisor 是 linux 的进程监视器, 它会自动启动您的控制台进程
我们在程序命令行下键入 yii queue/listen 就可以启动流水线了
当然你还可以通过 yii queue/info 来看看当前队列的情况等等
ok
一个简单的队列就实现了
来源: http://www.jianshu.com/p/b3e00552329b