研究think-queue 的时候,官方文档写得太简单,网络上相关介绍太少。所以我打算写一篇文章,方便新手学习。
官方文档:https://github.com/top-think/think-queue
支持3种驱动类型:
- sync同步执行
- 数据库驱动
- Redis驱动
快速上手,直接用数据库驱动
- 首页需要创建一个表
- 修改配置文件 config/queue.php 中的驱动方式和table名:jobs
CREATE TABLE `tp_jobs` (
`id` int(11) NOT NULL,
`queue` varchar(255) NOT NULL,
`payload` longtext NOT NULL,
`attempts` tinyint(3) UNSIGNED NOT NULL,
`reserved` tinyint(3) UNSIGNED NOT NULL,
`reserve_time` int(10) UNSIGNED DEFAULT NULL,
`available_time` int(10) UNSIGNED NOT NULL,
`create_time` int(10) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
1、创建任务类
任务类不需继承任何类,如果这个类只有一个任务,那么就只需要提供一个fire方法就可以了
namespace app\job;
use think\facade\Log;
use think\queue\Job;
class que
{
public function fire(Job $job)
{
Log::error("开始任务");
if ($job->attempts() > 1) {
Log::error("这个任务已经重试了".$job->attempts()."次");
}
//如果任务执行成功后 记得删除任务,不然这个任务会重复执行,直到达到最大重试次数后失败后,执行failed方法
$job->delete();
Log::error("删除该任务");
}
public function failed()
{
Log::error("fail++");
// ...任务达到最大重试次数后,失败了
}
2、将任务放入队列
访问如下控制器,会在数据库中多一条记录
namespace app\controller;
use app\job\que;
use think\facade\Queue;
class Index
{
public function index()
{
$this->create();
}
//监听任务并执行
public function start()
{
//$res=exec("php -v");
$res=exec("php ../think queue:work");
dump($res);
}
//创建同步任务
public function create()
{
$res=Queue::push(que::class,"test");
dump($res);
}
//创建异步任务
public function create2()
{
//延迟10秒执行
$res=Queue::later(10,que::class,"test");
dump($res);
}
}
3、监听任务并执行
queue:work - 这是一个新的后台进程(不再需要 daemon 标记), 这种方式运行,框架只会启动一次,并保持循环去消费队列,除非出现异常否则该进程将无限时间运行下去。这种方式消耗的 cpu 和 内存 都比 queue:listen 要少,因为在整个生命周期中框架一直是在保持运行状态。同时,使用该方法时如果更新了代码,记得使用 queue:restart 来重启。
queue:work --once - 该方法会启动框架,运行 job,然后销毁掉。在开发和测试代码的时候使用比较合适,因为每次都会加载一遍代码嘛。
queue:listen - 这种方式运行,框架每次都会启动,运行 job,然后关闭,然后再次启动框架,运行 job,然后关闭,这样一直循环(每次运行完一次都会完全释放掉运行时的内存和进程)。所以这种方式你不用担心代码的热更新,不用去重启 queue,随之而来的另外一个好处是不用去担心 queue:work 带来的内存泄漏。
php think queue:restart 停止所有消息队列
如何通过控制器/代码执行PHP命令(不推荐)
public function start() {
//exec("php -v");
exec("php ../think queue:work");
}
4、使用场景
如下单后10分钟不支付即关闭订单
只需要在下单后执行 Queue::later(60*10,que::class,[id=>1]);
用参数订单ID更新订单状态,多个订单之间互不干扰,但记得成功后需删除任务
5、配合supervisor使用,保证进程常驻
supervisor是用Python开发的一个client/server服务,是Linux/Unix系统下的一个进程管理工具。可以很方便的监听、启动、停止、重启一个或多个进程。用supervisor管理的进程,当一个进程意外被杀死,supervisor监听到进程死后,会自动将它重启,很方便的做到进程自动恢复的功能,不再需要自己写shell脚本来控制。
宝塔面板-软件商店中直接安装即可