Laravel 5:多个工作人员 - 无法删除作业 XXXXXX:NOT_FOUND

Laravel 5: Multiple workers - Cannot delete job XXXXXX: NOT_FOUND

我正在使用 Laravel 5 创建一个网站。我正在使用带有 2 个管的 beanstalkd 队列。我有 10 名工人由 daemontools 监控。 5个工人加工管子A和管子B。另外5个工人只加工管子B。

大部分时间一切正常,但偶尔 B 管似乎会锁死。日志显示工作人员抛出异常。

[2015-04-24 07:09:36] local.ERROR: exception 'Pheanstalk\Exception\ServerException' with message 'Cannot delete job 273812: NOT_FOUND' in /x/website/vendor/pda/pheanstalk/src/Command/DeleteCommand.php:44
Stack trace:
#0 /x/website/vendor/pda/pheanstalk/src/Connection.php(121): Pheanstalk\Command\DeleteCommand->parseResponse('NOT_FOUND', NULL)
#1 /x/website/vendor/pda/pheanstalk/src/Pheanstalk.php(384): Pheanstalk\Connection->dispatchCommand(Object(Pheanstalk\Command\DeleteCommand))
#2 /x/website/vendor/pda/pheanstalk/src/Pheanstalk.php(67): Pheanstalk\Pheanstalk->_dispatch(Object(Pheanstalk\Command\DeleteCommand))
#3 /x/website/vendor/laravel/framework/src/Illuminate/Queue/Jobs/BeanstalkdJob.php(73): Pheanstalk\Pheanstalk->delete(Object(Pheanstalk\Job))
#4 /x/website/vendor/laravel/framework/src/Illuminate/Queue/CallQueuedHandler.php(46): Illuminate\Queue\Jobs\BeanstalkdJob->delete()
#5 /x/website/vendor/laravel/framework/src/Illuminate/Queue/Jobs/Job.php(126): Illuminate\Queue\CallQueuedHandler->call(Object(Illuminate\Queue\Jobs\BeanstalkdJob), Array)
#6 /x/website/vendor/laravel/framework/src/Illuminate/Queue/Jobs/BeanstalkdJob.php(51): Illuminate\Queue\Jobs\Job->resolveAndFire(Array)
#7 /x/website/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(207): Illuminate\Queue\Jobs\BeanstalkdJob->fire()
#8 /x/website/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(159): Illuminate\Queue\Worker->process('beanstalkd', Object(Illuminate\Queue\Jobs\BeanstalkdJob), '20', '120')
#9 /x/website/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(113): Illuminate\Queue\Worker->pop(NULL, NULL, '120', 3, '20')
#10 /x/website/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(85): Illuminate\Queue\Worker->runNextJobForDaemon(NULL, NULL, '120', 3, '20')
#11 /x/website/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(101): Illuminate\Queue\Worker->daemon(NULL, NULL, '120', 128, 3, '20')
#12 /x/website/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(67): Illuminate\Queue\Console\WorkCommand->runWorker(NULL, NULL, '120', 128, true)
#13 [internal function]: Illuminate\Queue\Console\WorkCommand->fire()
#14 /x/website/vendor/laravel/framework/src/Illuminate/Container/Container.php(523): call_user_func_array(Array, Array)
#15 /x/website/vendor/laravel/framework/src/Illuminate/Console/Command.php(115): Illuminate\Container\Container->call(Array)
#16 /x/website/vendor/symfony/console/Symfony/Component/Console/Command/Command.php(257): Illuminate\Console\Command->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#17 /x/website/vendor/laravel/framework/src/Illuminate/Console/Command.php(101): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#18 /x/website/vendor/symfony/console/Symfony/Component/Console/Application.php(874): Illuminate\Console\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#19 /x/website/vendor/symfony/console/Symfony/Component/Console/Application.php(195): Symfony\Component\Console\Application->doRunCommand(Object(Illuminate\Queue\Console\WorkCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#20 /x/website/vendor/symfony/console/Symfony/Component/Console/Application.php(126): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#21 /x/website/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(94): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#22 /x/website/artisan(36): Illuminate\Foundation\Console\Kernel->handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#23 {main}

我想知道这个问题是否可能是由多个工人从事同一份工作引起的。这可能吗,或者是否有某种互斥锁来控制它?

还有什么可能导致这种情况?

有同样的问题。我的工作需要 60 多秒才能完成。增加默认管上配置队列中的 ttr 值就可以了。 希望对您有所帮助。

排队的命令花费的时间太长,问题是由 beanstalkd 中管上的 TTR 值引起的,但没有必要更改该值。

简而言之,beanstalkd 只会将作业保留最长时间(直到 TTR),然后它会假定出现问题并且 return 作业恢复到就绪状态状态。

相反,可以定期触摸作业以重置预订计时器。

在 Laravel 中,我已将它添加到我的 App\Commands\Command class 中,并且我会定期在长 运行 作业的循环中调用它。

public function touch()
{
    if (method_exists($this->job, 'getPheanstalk')) {
        $this->job->getPheanstalk()->touch($this->job->getPheanstalkJob());
    }
}

为了更精确地触摸,您可以使用上面提供的工作功能并在您的作业中执行以下操作:

1) 声明一个 属性 并在构造函数中设置它的值:

Protected $ttr;

public function __construct() {
    $this->ttr = time();
}

2) 然后测量循环内的时间差。在我的例子中,我下载并裁剪了数千张图片,所以在那个循环中我插入了以下内容:

//With a ttr of 60.
if((time() - 50) >= $this->ttr) { //If over 50 seconds since ttr start,
    $this->touch(); //reset ttr, 
    $this->ttr = time(); //and set new time.
}