运用supervisor管理thinkqueue 和swoole推送

安装think-queue

composer require topthink/think-queue

在这里插入图片描述
我这边是使用在自动确认订单方面

/**
     * 接单
     */
    public function receivingOrder()
    {
        $user_id = $this->auth->id;
        $this->checkIdentity();

        $oid = input('oid',0,'intval');
        if (!$oid) $this->error('订单不存在');

        $orderData = Order::where('id',$oid)->find();
        if (!$orderData) $this->error('订单不存在');
        if ($orderData->status != 0) $this->error('此单已被抢走了');
        Db::startTrans();
        try{
            //修改订单
            $orderData->consumer_id = $user_id;
            $orderData->status = 1;
            $orderData->save();

            //加入司机订单
            OrderConsumer::insert([
                'oid' => $oid,
                'consumer_id' => $user_id,
                'order_status' => 0,
                'createtime' => time(),
            ]);

            // 当前任务由哪个类负责处理
            $job_handler_classname = "app\job\job\ProductCheckOrder";
            // 当前队列归属的队列名称
            $job_queue_name = "product_order";
            // 当前任务所需的业务数据
            $job_data = ["order_id"=>$oid , 'user_id'=>$user_id];
            $time = Db::name('config')->where('name','auto_order_check')->value('value');
            $times = (int)$time*60;
            // 将任务推送到消息队列等待对应的消费者去执行
            $is_pushed = Queue::later($times,$job_handler_classname, $job_data, $job_queue_name);
            if($is_pushed === false){
                throw new Exception('自动确认订单队列失败');
            }

            Db::commit();
        }catch (\Exception $e){
            Db::rollback();
            $this->error('接单失败');
        }

        $this->success('接单成功,等待车主确认订单');
    }

自行建立队列
在这里插入图片描述
下面是队列代码 , 有点乱 , 小项目 , 懒得优化了

class ProductCheckOrder
{
	 /**
     * 车主自动确认订单
     */
    public function fire(Job $job, $data){
        $oid = $data['order_id'];
        $user_id = $data['user_id'];
        if (!$oid || !$user_id){
            $job->delete();
            return false;
        }

        $order = Db::name('order')->where(['consumer_id'=>$user_id , 'id'=>$oid ,'status'=>1,'product_confirm'=>0])->find();
        $order_consumer = Db::name('order_consumer')->where(['consumer_id'=>$user_id , 'oid'=>$oid,'order_status'=>0])->order('id desc')->find();

        if (!$order || !$order_consumer){
            $job->delete();
        }
        $res=0;
        Db::startTrans();
        try{
            $res1 = Db::name('order')->where('id',$order['id'])->update(['product_confirm'=>1]);
            $res2 =  Db::name('order_consumer')->where('id',$order_consumer['id'])->update(['order_status'=>1]);
            if (!$res1 || !$res2){
                throw new Exception('失败');
            }
            $res = 1;
            Db::commit();
        }
        catch (\Exception $e){
            Db::rollback();
        }

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

下面是启动队列 , 在项目根目录下使用 php think queue:work --queue product_order
注意 , 不要加daemon , 毕竟开发时需要调整 , 否则会不断的 ps -apn 和kill -9


接下来使用swoole去完成消息推送

<?php
/*
Create By 2021/7/5 - 13:59 - Delimma
To overcome difficulties!
*/
namespace app\console;

use app\common\library\Token;
use app\common\model\OrderPath;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\Db;

class Swoole extends Command
{
    // Server 实例
    protected $server;
    protected function configure(){
        $this->setName('websocket:start')->setDescription('订单弹窗');
    }
    protected function execute(Input $input, Output $output){
        // 监听所有地址,监听 10000 端口
        $this->server = new \swoole_websocket_server('0.0.0.0', 9502);
        $this->server->set([
            'max_conn' => 50,
            'max_request' => 50,
            'daemonize' => false
        ]);
        // 设置 server 运行前各项参数
        // 调试的时候把守护进程关闭,部署到生产环境时再把注释取消
        // $this->server->set([
        //     'daemonize' => true,
        // ]);

        // 设置回调函数
        $this->server->on('Open', [$this, 'onOpen']);
        $this->server->on('Message', [$this, 'onMessage']);
        $this->server->on('Close', [$this, 'onClose']);
        Db::name('swoole_restart')->insert(['time'=>time()]);
        $this->server->start();

    }


    // 建立连接时回调函数
    public function onOpen(\swoole_websocket_server $server, \swoole_http_request $request){
//        echo "用户{$request->fd}加入。\n";
    }

    // 收到数据时回调函数
    public function onMessage(\swoole_websocket_server $server, \swoole_websocket_frame $frame){
        $data = json_decode($frame->data,true);
        if (empty($data['token']) || !isset($data['token'])){
            return false;
        }
        if (empty($data['type']) || !isset($data['type'])){  // open 连接时关联映射 ,  send 发送数据
            return false;
        }
        $user = Token::get($data['token']);
        if (!$user) {
            return false;
        }
        $user_id = intval($user['user_id']);
        $user_type = Db::name('user')->where('id',$user_id)->value('identity',2);
        if ($data['type'] == 'open' && $user_type != 2){
            // 连接时建立映射
            $uuid = Db::name('swoole_fd')->where('uid',$user_id)->find();
            if (!$uuid){
                // 没有映射关系
                Db::name('swoole_fd')->insert(['uid'=>$user_id ,'fd'=>$frame->fd, 'time'=>time() ,'identity'=>$user_type]);
            }else{
                //更新映射
                Db::name('swoole_fd')->where(['uid'=>$user_id])->update(['fd'=>$frame->fd , 'time'=>time(),'identity'=>$user_type]);
            }
        }

        /**
         * 发送订单
         */
        if ($data['type'] == 'sendorder'){
            if (empty($data['oid']) || !isset($data['oid'])){
                return false;
            }else{
                $oid = intval($data['oid']);
            }
            // 查询订单 , 查询fd , 推送消息
            $order = Db::name('order')->where(['consumer_id'=>$user_id ,'id'=>$oid])->find();
            if (!$order){
                return false;
            }
            //车主映射
            $product_fd = Db::name('swoole_fd')->where('uid',$order['product_id'])->where('identity',0)->order('id desc')->find();
            if (!$product_fd) return false;
            $swoole_restart = Db::name('swoole_restart')->order('id desc')->find();
            if ($product_fd['time'] < $swoole_restart['time'])  return false;
            $server->push($product_fd['fd'],json_encode($order));
        }

        /**
         * 地图轨迹
         */
        if ($data['type'] == 'sendpath'){
            if (empty($data['oid']) || !isset($data['oid']) ||empty($data['lat']) || !isset($data['lat']) ||empty($data['lng']) || !isset($data['lng'])){
                return false;
            }else{
                $oid = intval($data['oid']);
            }
            // 查询订单 , 查询fd , 保存轨迹
            $order = Db::name('order')->where(['consumer_id'=>$user_id ,'id'=>$oid,'product_confirm'=>1])->where('final_price',0)->find();
            if (!$order){
                return false;
            }
            $path = OrderPath::where(['oid'=>$oid ,'uid'=>$user_id])->find();
            $pathdata = $data['lat'].','.$data['lng'];

            if (!$path){
                echo '1';
                OrderPath::insert(['oid'=>$oid ,'uid'=>$user_id ,'path'=>$pathdata]);
            }else{
                echo '2';
                $path->path = $path->path . '/' . $pathdata;
                $res = $path->save();
                if (!$res){
                    echo '失败'.PHP_EOL;
                }
            }
        }


    }



    // 连接关闭时回调函数
    public function onClose($server, $fd){
        Db::name('swoole_fd')->where('fd',$fd)->delete();
//        echo "client {$fd} closed \n";
    }

}

onMessage里写自己的代码逻辑, 这里我直接复制了 , 懒得弄了 , 我监听的是9502
在这里插入图片描述

设置自定义TP命令

在上图的command.php中

<?php
return [
    'app\admin\command\Crud',
    'app\admin\command\Menu',
    'app\admin\command\Install',
    'app\admin\command\Min',
    'app\admin\command\Addon',
    'app\admin\command\Api',
    'app\console\Swoole',  // 添加這個
];

然后就可以在项目根目录输入php think 查看是否存在自定义命令

在这里插入图片描述

这篇文章到这吧

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苗先生的PHP记录

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值