laravel 作业尝试次数过多或运行时间过长

7dl7o3gd  于 2022-12-24  发布在  其他
关注(0)|答案(6)|浏览(368)

我有一个作业在本地运行得完美无缺,但在生产中却遇到了无法运行的问题。我用一个try/catch覆盖了整个handle(),没有看到任何记录到Bugsnag的内容,尽管在其他地方部署了许多其他例外。

public function handle() {
    try {

        // do stuff

    } catch (\Exception $e) {
        Bugsnag::notifyException($e);

        throw $e;
    }
}

根据Laravel Horizon,此队列作业运行0.0026001930236816406秒,我从未看到它工作,也从未在failed_jobs表中看到与此作业相关的任何其他错误。

    • 配置文件/队列. php**
'redis' => [
        'driver' => 'redis',
        'connection' => 'default',
        'queue' => 'default',
        'retry_after' => (60 * 10), // 10 minutes
        'block_for' => null,
    ],
    • 配置文件/地平线. php**
'environments' => [
    'production' => [
        'supervisor'        => [
            'connection'    => 'redis',
            'queue'         => [
                'default',
            ],
            'balance'       => 'auto',
            'processes'     => 10,
            'tries'         => 3,

            // 10 seconds under the queue's retry_after to avoid overlap
            'timeout'       => (60 * 10) - 10, // Just under 10 mins
        ],

如果某个原因导致此作业一次又一次地重试,我如何才能找到原因?我不知所措。

    • 迄今为止的调查**
  • 我的期望是我应该能够运行查询:
SELECT DISTINCT exception, COUNT(id) as errors
FROM failed_jobs 
WHERE payload LIKE '%[TAG-JOB-HAS]%' 
GROUP BY exception;

要查看此错误消息以外的内容:
作业尝试次数过多或运行时间过长
但我只看到这些。

  • Laravel Horizon的 Jmeter 板显示有问题的作业运行了不到1秒,所以我知道它实际上没有超时。
xcitsw88

xcitsw881#

我也有同样的问题
我通过增加“retry_after”参数修复了它
确保retry_after值大于作业运行所需的时间
配置/队列.php文件中

'connections' => [

    'sync' => [
        'driver' => 'sync',
    ],

    'database' => [
        'driver' => 'database',
        'table' => 'jobs',
        'queue' => 'default',
        'retry_after' => 9000,
    ],
wwtsj6pe

wwtsj6pe2#

尝试捕获laravel给出的失败方法中的异常

/**
* The job failed to process.
*
* @param  Exception  $exception
* @return void
*/
public function failed(Exception $exception)
{
    // Send user notification of failure, etc...
}

并检查本地中的默认队列驱动程序是否同步,然后检查其预期行为。

t1rydlwq

t1rydlwq3#

根据文档,您可以通过两种常见方式处理作业失败:

  • 使用失败的作业事件
  • 使用failed()方法。

在第一种情况下,你可以使用Queue::failing()方法处理所有的作业,你会收到Illuminate\Queue\Events\JobFailed事件作为一个参数,它包含了exception。
在另一种情况下,你可以使用failed()方法,它应该放在你的handle()方法附近。你也可以接收Exception $exception作为参数。
示例:

public function failed(\Throwable $exception)
{
    // Log failure
}

希望这个有用。

sigwle7e

sigwle7e4#

如果您在错误日志或failed_jobs表中看到了MaxAttemptsExceededException,但不知道作业发生了什么,那么让我来解释一下可能发生了什么。

The job timed out and it can't be attempted again.
The job was released back to the queue and it can't be attempted again.

如果您的作业处理时间超过了超时配置,工作线程将检查允许的最大尝试次数和作业的到期日期,并决定是否可以再次尝试。如果不可能,工作线程将只将作业标记为失败并抛出MaxAttemptsExceededException
另外,如果作业被释放回队列,并且工作线程拾取它,它将首先检查是否超过了允许的最大尝试次数,或者作业已经过期,在这种情况下抛出MaxAttemptsExceededException
https://divinglaravel.com/job-has-been-attempted-too-many-times-or-run-too-long

wdebmtf2

wdebmtf25#

也许这会帮助一些人:不要在排队的任务中使用dd()

vnjpjtjt

vnjpjtjt6#

我也有同样的问题
我通过在Job类中使用以下代码解决了这个问题。

public $failOnTimeout = false;

如果超时或作业失败,它将继续。我还增加了超时时间。

public $timeout = 120000;

Reference : https://laravel.com/docs/9.x/queues#failing-on-timeout

相关问题