tp 队列分享

一、安装queue扩展,有的下载后框架可能自带queue扩展。

composer require topthink/think-queue
"repositories": {
        "packagist": {
            "type": "composer",
            "url": "https://packagist.org"
        }
    }

 

二、配置(服务器需要安装有redis):

配置文件位于 application/extra/queue.php

return [
//    'connector' => 'Sync'
    'connector'  => 'Redis',        // Redis 驱动
    'expire'     => 60,        // 任务的过期时间,默认为60秒; 若要禁用,则设置为 null
    'default'    => 'default',        // 默认的队列名称
    'host'       => '127.0.0.1',    // redis 主机ip
    'port'       => 6379,        // redis 端口
    'password'   => '',        // redis 密码
    'select'     => 1,        // 使用哪一个 db,默认为 db0
    'timeout'    => 0,        // redis连接的超时时间
    'persistent' => false,        // 是否是长连接
];

三、代码:

创建一个控制器,执行队列里的任务,例如创建一个app\message\controller\DoJob.php。

<?php
/**
* 文件路径: \application\index\job\Hello.php
* 这是一个消费者类,用于处理 helloJobQueue 队列中的任务
*/
namespace app\job;
use think\queue\Job;
use think\Db;

class Test {
  /**
  * fire方法是消息队列默认调用的方法
  * @param Job $job 当前的任务对象
  * @param array|mixed $data 发布任务时自定义的数据
  */
  public function fire(Job $job,$data){

    $userId = isset($data['userId'])?$data['userId']:'';
    $id=isset($data['id'])?$data['id']:'';
    $episode=isset($data['episode'])?$data['episode']:'';
    $progress=isset($data['progress'])?$data['progress']:'';

    if(strpos($id,',')) {
      $to_ids=explode(',',$id);
      foreach($to_ids as $v) {
        Db::name('history_film')->insert(['user_id'=>$userId,'video_id'=>$v,'episode_id'=>$episode,'create_time'=>time(),'update_time'=>time()]);
      }
      $job->delete();
      return;
    }

    if(Db::name('history_film')->where(['user_id'=>$userId,'video_id'=>$id,'episode_id'=>$episode])->find()) {
      Db::name('history_film')->where(['user_id'=>$userId,'video_id'=>$id,'episode_id'=>$episode])->update(['progress'=>$progress,'update_time'=>time()]);
      Db::name('history_all')->where(['user_id'=>$userId,'video_id'=>$id,'episode_id'=>$episode])->update(['progress'=>$progress,'update_time'=>time()]);
    } else {
      $data = ['user_id'=>$userId,'video_id'=>$id,'episode_id'=>$episode,'create_time'=>time(),'update_time'=>time()];
      Db::name('history_film')->insert($data);
      $data = ['user_id'=>$userId,'video_id'=>$id,'episode_id'=>$episode,'type'=>1,'create_time'=>time(),'update_time'=>time()];
      Db::name('history_all')->insert($data);
    }
    $job->delete();
    return;

// 如有必要,可以根据业务需求和数据库中的最新数据,判断该任务是否仍有必要执行.
// $isJobStillNeedToBeDone = $this->checkDatabaseToSeeIfJobNeedToBeDone($data);
// if(!$isJobStillNeedToBeDone){
// $job->delete();
// return;
// }

// $isJobDone = $this->doHelloJob($data);

// if ($isJobDone) {
// //如果任务执行成功, 记得删除任务
// $job->delete();
// }else{
// if ($job->attempts() > 3) {
// //通过这个方法可以检查这个任务已经重试了几次了
// $job->delete();
// // 也可以重新发布这个任务
// //$job->release(2); //$delay为延迟时间,表示该任务延迟2秒后再执行
// }
// }
}

/**
* 有些消息在到达消费者时,可能已经不再需要执行了
* @param array|mixed $data 发布任务时自定义的数据
* @return boolean 任务执行的结果
*/
private function checkDatabaseToSeeIfJobNeedToBeDone($data){
return true;
}

/**
* 根据消息中的数据进行实际的业务处理
* @param array|mixed $data 发布任务时自定义的数据
* @return boolean 任务执行的结果
*/
private function doHelloJob($data) {
// 根据消息中的数据进行实际的业务处理...
// test
if (!empty($data)) {

}
return true;
}
}

发布任务到队列中,创建一个测试代码,例如创建一个app\message\controller\addJob.php:

<?php
/**
* Created by PhpStorm.
* User: apple
* Date: 2021/5/16
* Time: 下午10:22
*/

namespace app\shell\command;

use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\Db;
use aliopensearch\AliOpenSearch;
use think\cache\driver\Redis;

use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
use AlibabaCloud\Airec\Airec;
use AlibabaCloud\OpenSearch\OpenSearch;
use api\user\model\VideoModel;
use api\user\model\VideoAllModel;
use OpenSearch\Client\DocumentClient;
use OpenSearch\Client\SearchClient;
use OpenSearch\Util\SearchParamsBuilder;
use OpenSearch\Client\OpenSearchClient;


use think\Queue;


class Queue extends Command
{
protected function configure()
{
parent::configure();
$this->setName('Test')->setDescription('Test');
}

protected function execute(Input $input, Output $output)
{
  //任务执行类(消费者消费的处理逻辑)
  $jobHandlerClassName = "app\job\Test@fire";
  //队列名,如不存在会自动创建
  $jobQueueName = "helloJobQueue";
  //推送的业务数据
  // $jobData = [ 'name' => 'test'.rand(), 'password'=>rand()];
  $jobData = [
    "userId"=> 1,
    "id"=> 1,
    "episode"=> 1,
    "progress"=> 400,
    ];
  //延迟推送,推送后等待消费者消费
  // $isPushed = Queue::later(300, $jobHandlerClassName , $jobData , $jobQueueName );
  //立即推送,等待消费者消费
  $isPushed = Queue::push($jobHandlerClassName , $jobData , $jobQueueName );
  // database 驱动时,返回值为 1|false ; redis 驱动时,返回值为 随机字符串|false
  if( $isPushed !== false ){
    echo date('Y-m-d H:i:s') . " a new Hello Job is Pushed to the MQ"."<br>";
  }else{
    echo 'Oops, something went wrong.';
  }

  echo "同步成功";
  }
}

四、监听任务并执行

在服务器上,执行框架的根目录下的think命令:

nohup /usr/local/bin/php /home/www/tp5/think queue:work --daemon --queue JobQueue &
posted @ 2022-04-27 14:06  知子  阅读(82)  评论(0编辑  收藏  举报