ThinkPHP 实现队列
应用场景:
队列适用与多个用户同时执行一个操作,或适用与单个用户多次执行同一个操作
- 用户订单提交
缺点:
一旦需处理数据加入到任务内就不能删除,如果删除可以使用redis
队列文件:
Tp6 config/queue.php 配置文件 ,启动reids 服务
/** * 消息队列配置 * 内置驱动:redis、database、topthink、sync */ return [ //sync驱动表示取消消息队列还原为同步执行 //'connector' => 'sync', //Redis驱动 'connector' => 'redis', "expire"=>60,//任务过期时间默认为秒,禁用为null "default"=>"default",//默认队列名称 "host"=>Env::get("redis.host", "127.0.0.1"),//Redis主机IP地址 "port"=>Env::get("redis.port", 6379),//Redis端口 "password"=>Env::get("redis.password", "123456"),//Redis密码 "select"=>5,//Redis数据库索引 "timeout"=>0,//Redis连接超时时间 "persistent"=>false,//是否长连接 //Database驱动 //"connector"=>"Database",//数据库驱动 //"expire"=>60,//任务过期时间,单位为秒,禁用为null //"default"=>"default",//默认队列名称 //"table"=>"jobs",//存储消息的表明,不带前缀 //"dsn"=>[], //Topthink驱动 ThinkPHP内部的队列通知服务平台 //"connector"=>"Topthink", //"token"=>"", //"project_id"=>"", //"protocol"=>"https", //"host"=>"qns.topthink.com", //"port"=>443, //"api_version"=>1, //"max_retries"=>3, //"default"=>"default" ];
app/queue/controller/Execjob 创建单个任务
namespace app\queue\controller; use think\queue\Job; use think\Exception; class Execjob { public function fire(Job $job, $data) { // 这里执行具体的任务,如果方法不存在,或参数出错,致命错误时 try{ //调用函数方法,如果使用ThinkPHP app\模块\控制器\类名@方法名,使用action方法 $result=call_user_func_array($data['action'],$data['param']); }catch (Exception $e){ // 错误处理 } if($result) { //如果任务执行成功后 记得删除任务,不然这个任务会重复执行,直到达到最大重试次数后失败后,执行failed方法 $job->delete(); }else{ $delay=config('config.fail_repeat_delay'); $job->release($delay); //如果执行失败,$delay为延迟时间重新执行 } $fail_exec_number=config('queue.fail_exec_number'); if ($job->attempts() > $fail_exec_number) { //通过这个方法可以检查这个任务已经重试了几次了 $job->delete(); } } public function failed(Execjob $job) { // ...任务达到最大重试次数后,失败了,可以添加一些其他的操作,会自动调用,如同 fire()方法 $job->delete(); } }
app/queue/controll/jobqueue.php 发布单个任务(其他页面调用当前方法)
namespace app\queue\controller; use think\Queue; class Jobqueue { /** * queueTest * @param $queue 调用任务类文件名 * @param $data array 执行方法的参数数据 action 具体任务方法名,param 方法名参数 * @param $delay 消息队列延迟时间,单位秒 */ public function queueTest(string $queue,array $data=[],int $delay){ //创建任务: 项目命名空间\控制器@方法 $job = "app\queue\controller\Execjob"; // 如果立即发送 if(!$delay){ /* * $job 类的命名空间\类名 app\queue * 其他的需要些完整的类名,需要写完整的类名 app\queue\controller\job * 如果一个任务类里有多个小任务的话,类的命名空间\类名@方法,app\queue\controller\Execjob2@task1,app\queue\controller\Execjob2@task2 * $data 是你要传到任务里的参数 * $queue 队列名,指定这个任务是在哪个队列上执行,同下面监控队列的时候指定的队列名,可不填 */ $result = Queue::push($job, $data, $queue); }else{ //如果延时发送 $result = Queue::later($delay, $job, $data, $queue); } //dump($result); // database 驱动时,返回值为 1|false ; redis 驱动时,返回值为 随机字符串|false // 当前页面为同步页面 } }
监听队列
写完之后再控制器切换到当前目录下执行,任务的监听、执行
// --queue 队列名称,不指定监听所有队列 php think queue:listen --queue send_mail
测试访问页面
http://tp.com/pub/test/index,任务的调用
<?php namespace app\pub\controller; use app\queue\controller\Jobqueue; use think\Controller; class Test extends Controller { public function index(){ $job_queue=new Jobqueue(); $job_queue->queueTest('send_mail',['develophp@foxmail.com','sa','测试']); // send_mail() 定义在common.php 文件中 } }
队列执行完成后,处于等待下次调用
队列流程:创建 ->发布 ->监听 -> 调用/推送 ->删除
调用多个任务
app/queue/controller/Execjob2 创建多个任务
namespace app\queue\controller; use think\queue\Job; class Execjob2{ public function task1(Job $job, $data){ // 具体任务 } public function task2(Job $job, $data){ // 具体任务 } // 还有个可选的任务失败执行的方法 failed 传入的参数为$data(发布任务时自定义的数据),会自动调用 public function failed($data){ // 任务执行失败调用当前方法 } }
app/queue/controll/jobqueue2.php 发布任务(直接调用)
namespace app\queue\controller; use think\Queue; class Jobqueue2 { public function queueTest(){ //....这里执行具体的任务 /* * $job 类的命名空间\类名 app\queue * 其他的需要些完整的类名,需要写完整的类名 app\queue\controller\job * 如果一个任务类里有多个小任务的话,类的命名空间\类名@方法,app\queue\controller\Execjob2@task1,app\queue\controller\Execjob2@task2 */ $job='app\queue\controller\Execjob2@task2'; $data=1; //是你要传到任务里的参数 $delay=config('config.fail_repeat_delay'); // 延迟时间,单位秒 $queue='work'; // 队列名,指定这个任务是在哪个队列上执行,同下面监控队列的时候指定的队列名,可不填 // 如果立即发送 if(!$delay){ $result = Queue::push($job, $data, $queue); }else{ //如果延时发送 $result = Queue::later($delay, $job, $data, $queue); } //dump($result); // database 驱动时,返回值为 1|false ; redis 驱动时,返回值为 随机字符串|false // 当前页面为同步页面 } }
监听队列
写完之后再控制器切换到当前目录下执行,任务的监听、执行
// --queue 队列名称,不指定监听所有队列 php think queue:listen --queue work // 或者 php think queue:listen php think queue:work
测试访问页面
http://tp.com/queue/jobqueue2/queueTest 任务的推送
队列执行完成后,处于等待下次调用
队列流程:创建 ->发布 ->监听 ->调用/推送 ->删除
相关文章:tp5.1_队列queue学习