laravel 队列延迟分发不生效

1. 运行环境

lnmp
centerOs

1). 当前使用的 Laravel 版本?

Laravel Framework 8.78.1

2). 当前使用的 php/php-fpm 版本?

PHP 版本:7.4.21

3). 当前系统

CentOS 7.6

4). 业务环境

开发环境, 无负载均衡

5). 相关软件版本

MySQL 5.7.34;
Redis 6.2.4

2. 问题描述?

问题:延迟队列不执行,或报超时错误
错误日志:

App\Jobs\SettlementOrder has been attempted too many times or run too long. The job may have previously timed out.

env 配置文件:

BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DRIVER=local
QUEUE_CONNECTION=redis
QUEUE_DRIVER=redis
REDIS_CLIENT=predis
SESSION_DRIVER=file
SESSION_LIFETIME=120

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

业务代码:

//分发任务
$jobRes = SettlementOrder::dispatch(['id' => 1])->delay(now()->addSeconds(60));

任务代码:

<?php

namespace App\Jobs;
....

class SettlementOrder implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $data;
    public function __construct($data)
    {
        $this->data = $data;
    }
    public function handle()
    {
        /**
         * 通过交易订单ID,查询订单信息
         */
        $findOrder = DB::table('trading_record')->where('id', '=', $this->data['id'])->first();
        $oldInfo = DB::table('members')->where('id', '=', $findOrder->member_id)->first();
        if ($findOrder->status === 2 && $findOrder->result === 1) {
            $WinTotalFee = 1;//业务逻辑计算
            $winMoney = 1;//
            $up = self::updateTrading($this->data['id'], 1);
            if ($up) {
                $income = DB::table('members')->where('id', '=', $findOrder->member_id)->increment('balance', $winMoney);
                if ($income) {
                    self::balanceBack($findOrder->member_id, $findOrder->total_fee, $oldInfo->balance);
                    self::incomeFunc($findOrder->member_id, $WinTotalFee, $oldInfo->balance);
                    return true;
                }
            }
            return false;
        }
        if ($findOrder->status === 2 && $findOrder->result === 2) {
            $loseTotalFee = bcmul($findOrder->total_fee, bcdiv($findOrder->earnings, 100, 2), 2); 
            $loseMoney = bcsub($findOrder->total_fee, $loseTotalFee, 2);
            //更新
            $up = self::updateTrading($this->data['id'], 2);
            if ($up) {
                $rolBack = DB::table('members')->where('id', '=', $findOrder->member_id)->increment('balance', $loseMoney);
                if ($rolBack) {
                    self::balanceBack($findOrder->member_id, $loseMoney, $oldInfo->balance);
                    self::incomeFunc($findOrder->member_id, $loseTotalFee, $oldInfo->balance, 1);
                    return true;
                }
            }
            return false;
        }
    }

    public static function updateTrading($id, $result)
    {
        $up = DB::table('trading_record')->where('id', '=', $id)->update([
            'status' => 1,
            'result' => $result,
            'updated_at' => date('Y-m-d H:i:s', time())
        ]);
        return $up;
    }

    public static function balanceBack($memberId, $totalFee, $balance)
    {
        return DB::table('income')->insert([
            'xxx' => xxx
        ]);
    }

    public static function incomeFunc($memberId, $totalFee, $balance, $type = 0)
    {
        return DB::table('income')->insert([
            'xxx' => xxx
        ]);
    }
}

尝试过执行的监听代码:

php artisan queue:listen
php artisan queue:work
php artisan queue:work redis
php artisan queue:work redis --daemon
php artisan queue:work --daemon

3. 您期望得到的结果?

能按时执行

4. 您实际得到的结果?

队列不执行

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
最佳答案

已解决,感谢各位大佬得热心解答,debug能力还是有待提高,但还是靠自己解决目前得需求了,指定唯一队列就好了。还是希望大佬们多多指教!!

2年前 评论
讨论数量: 35
chowjiawei

->onQueue('trading') 你都指定队列名字了 你执行的队列又没有这个队列 当然超时不生效了

2年前 评论
Authoz (楼主) 2年前

从这个报错看起来,你的队列是有执行的,并进行了多次重试,应该是你的队列业务代码有问题,里面的处理流程,应该存在死循环之类的,或者长时间阻塞

2年前 评论
Authoz (楼主) 2年前
忆往昔弹指间 (作者) 2年前
Authoz (楼主) 2年前
Authoz (楼主) 2年前
忆往昔弹指间 (作者) 2年前
Authoz (楼主) 2年前

我之前也遇到过这个问题,到现在也不知道为啥,队列的逻辑很简单,应该是瞬间能执行完,但是就是隔了很长时间

2年前 评论
Authoz (楼主) 2年前
勇敢的心 (作者) 2年前
Authoz (楼主) 2年前

看下错误日志有没有报错 storage/logs/laravel.log

之前我遇到过队列消失了,数据没有变,以为队列没有执行,最后在错误日志里面找到了,是代码也报错,队列没有执行

2年前 评论
Authoz (楼主) 2年前
kis龍 (作者) 2年前
Authoz (楼主) 2年前

业务代码没仔细看,看了评论的结论,我也认为是业务代码的问题。

脚本执行超时,排查方法,把队列先改成同步,分发一次,看看是否还超时,如果超时的话就是业务代码的问题。

2年前 评论
Authoz (楼主) 2年前

一坨代码拿到别的地方测试,这里全都注释掉,就打简单的 log,先确定执不执行。

2年前 评论
Authoz (楼主) 2年前

建议在job里打log,看一下哪里没走通。这个需要逐步排查的。把业务代码先注释掉。

2年前 评论
Authoz (楼主) 2年前
GDDD

可以负责任的告诉你,任务已经执行,你业务代码有问题,从最开始调试吧

2年前 评论
Authoz (楼主) 2年前
GDDD (作者) 2年前
Authoz (楼主) 2年前
GDDD (作者) 2年前
GDDD (作者) 2年前
Authoz (楼主) 2年前
Authoz (楼主) 2年前

job本身有有个默认最长执行时间,好像是120s?以前用的时候报过错,到了就自动kill了,可以改这个参数的。 可以try一下看看是什么报错,或者切换成同步看下逻辑是否有问题

2年前 评论
Authoz (楼主) 2年前

已解决,感谢各位大佬得热心解答,debug能力还是有待提高,但还是靠自己解决目前得需求了,指定唯一队列就好了。还是希望大佬们多多指教!!

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!