tp5,把耗时操作转为队列,queue + redis + supervisor消息推送(队列的执行异步不异步不知道,workman,swoole可以异步)
添加队列
/** * 发送一个推送 * @param mixed client_id 设备号(字符串/数组) 1 * @param int group 分组(如:1=用户端2=骑手端) 1 * @param msg_type 透传消息类型 * @param order_id 订单ID * @return mixed * @author xuefeiniao * @date 2022/2/25 1:44 下午 */ public static function send_notice($data) { $dataArr = [ 'type' => 2, 'client_id' => $data['client_id'], 'template_type' => 3, 'group' => $data['group'], 'title' => '', 'content' => '', 'payload' => json_encode(['type' => 2,'msg_type'=>$data['msg_type'], 'order_id' => $data['order_id']]) ]; // 1.当前任务将由哪个类来负责处理。 // 当轮到该任务时,系统将生成一个该类的实例,并调用其 fire 方法 // $jobHandlerClassName = 'app\common\OrderNotice'; $jobHandlerClassName = 'app\common\job\OrderNotice'; // 2.当前任务归属的队列名称,如果为新队列,会自动创建 $jobQueueName = "SendRiderNoticeJobQueue"; // 3.当前任务所需的业务数据 . 不能为 resource 类型,其他类型最终将转化为json形式的字符串 // 4.将该任务推送到消息队列,等待对应的消费者去执行 $res = Queue::push( $jobHandlerClassName , $dataArr , $jobQueueName ); }
消费队列
<?php /** * Created by PhpStorm. * User: Administrator * Date: 2020/3/18 0018 * Time: 14:36 */ namespace app\common\job; use think\Db; use think\facade\Log; use think\queue\Job; use app\operation\model\SystemMessage; class OrderNotice { /** * fire方法是消息队列默认调用的方法,tp5.1中,调用的类是 $jobHandlerClassName = 'app\lives\job\SendGift'; * @param Job $job 当前的任务对象 * @param array|mixed $data 发布任务时自定义的数据 */ public function fire(Job $job,$data){ //根据消息中的数据进行实际的业务处理... $isJobDone = $this->doJob($data); // file_put_contents("1.txt",json_encode($isJobDone).PHP_EOL, FILE_APPEND); if ($isJobDone) { //如果任务执行成功, 记得删除任务 $job->delete(); }else{ if ($job->attempts() > 2) { //通过这个方法可以检查这个任务已经重试了几次了 /// Log::info('自动取消订单执行失败,已经重试好多次'); $job->delete(); // 也可以重新发布这个任务 //print("<info>Hello Job will be availabe again after 2s."."</info>\n"); //$job->release(2); //$delay为延迟时间,表示该任务延迟2秒后再执行 } // Log::info('推送消息失败'); } } /** * 发送消息推送 * 根据消息中的数据进行实际的业务处理 * @param array|mixed $data 发布任务时自定义的数据 * @return boolean 任务执行的结果 */ private function doJob($data) { // 个推 (zb 框架) $res = addons_action('Getui/Getui/pushMessageToList', [$data]); // jpush (fastadmin) // $objectPush = new \addons\gpush\controller\Index; // switch ($type) { // case 1: // $res = $objectPush->pushMessageToSingle($data, $clientId, $template_type, $group); // // break; // case 2: // $res = $objectPush->pushMessageByTag($data, $clientId, $template_type); // break; // case 3: // $res = $objectPush->pushMessageToApp($data, $clientId, $template_type); // break; // case 4: // $res = $objectPush->pushMessageToList($data, $clientId, $template_type); // break; // } if($res){ return true; }else{ return false; } } }
修改redis配置(如项目中未用到,用到可忽略,如不配置无法加入队列)
如果队列,不用redis存储也可以用数据库存储,那么就必须建表(存储队列的表) tp规定 表名为:前缀_jobs
/* Navicat Premium Data Transfer Source Server : localhost Source Server Type : MySQL Source Server Version : 50553 Source Host : localhost:3306 Source Schema : ordershop Target Server Type : MySQL Target Server Version : 50553 File Encoding : 65001 注意:sql中的表前缀为:tp */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for tp_jobs -- ---------------------------- DROP TABLE IF EXISTS `tp_jobs`; CREATE TABLE `tp_jobs` ( `id` int(11) NOT NULL AUTO_INCREMENT, `queue` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `payload` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `attempts` 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, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; SET FOREIGN_KEY_CHECKS = 1;
修改queue 配置文件
return [ // 'connector' => 'Sync' // 系统文件存储,会立即执行推送而非队列 'connector' => 'Redis', // Redis 驱动 'expire' => 900, // 任务的过期时间,默认为60秒; 若要禁用,则设置为 null 'default' => 'chat', // 默认的队列名称 'host' => '127.0.0.1', // redis 主机ip 'port' => 6379, // redis 端口 'password' => 'redis密码', // redis 密码 'select' => 10, // 使用哪一个 db,默认为 db0 'timeout' => 0, // redis连接的超时时间 'persistent' => false, // 是否是长连接 ]
其他
1.下载supervisor
配置
项目目录,而非public目录
2.启动命令(–daemon 表示执行完不退出,多次执行,不加表示执行完任务退出)
tp5.1
php think queue:work --queue SendRiderNoticeJobQueue [--daemon]
tp5.0
php /www/wwwroot/路径/think queue:work --queue order_queue_name --daemon
3.下载redis数据管理工具
桌面版的redis管理工具(Another Redis DeskTop Manager)
宝塔面板的错误:
有时会打开报错:AttributeError: ‘list’ object has no attribute ‘decode’
参考文章修改报错修复
转: https://blog.csdn.net/qq_36957701/article/details/123219085