2015-04-24 32 views
8

我創建了一個使用Laravel 5的網站。我使用的beanstalkd與2管隊列。我有10名工作人員使用守護進程監控。 5名工人處理A管和B管。其他5名工人只處理管B。Laravel 5:多名工人 - 無法刪除工作XXXXXX:NOT_FOUND

事情大部分時間工作很好,但偶爾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} 

我想知道如果問題可能是由幾個工人去同一個工作。這是可能的還是有某種類型的互斥來控制呢?

還有什麼可能導致這種情況?

回答

13

排隊的命令花費的時間太長,問題是由beanstalkd中的TTR值引起的,但沒有必要更改該值。

簡而言之,beanstalkd只會將作業保留最長時間(直到TTR),然後它會認爲出現了問題並將作業返回到就緒狀態。

取而代之,可以定期觸摸作業來重置預約計時器。

在Laravel中,我已經將它添加到我的App \ Commands \ Command類中,並且我定期在長時間運行的作業中將其稱爲循環內部。

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

我能得到一些關於我如何實現這一點的說明嗎?如果您說需要將它添加到App \ Command中,那麼您是否說我創建了一個名爲TouchCommand.php的新命令,例如,因爲在命令中我所看到的通常都是構造函數和句柄,所以不確定它會發生什麼。那麼在我的實際工作中,我怎麼稱呼它? – dmotors

+0

您可以直接將該函數直接放入Command類。您的其他命令類將從其中延伸並繼承該功能。然後在他們的handle()方法中,您可以定期調用$ this-> touch()來重置計時器。 – Kebian

+3

僅供參考我在我的抽象Job類中使用了這段代碼,然後從長時間運行的作業中調用該方法。 – george

1

有同樣的問題。我的工作超過60秒完成。在默認管道中增加配置隊列中的ttr值有訣竅。 希望有所幫助。

+0

謝謝。我也設法將它隔離到需要很長時間才能完成的工作。根據您的建議優化我的代碼並更改ttr可能會解決此問題。我會在這裏更新我的發現。 – Kebian

+1

如果你的任務是冪等的,那麼這將是確定的,否則只是想想如果任務突然需要更長時間會發生什麼?保持接觸工作的方法更安全。這也允許你只將它應用到你想要的工作而不是整個隊列。有些項目可能永遠不需要很長時間,實際上可能會很快被抓住。 –

0

要與你的接觸更精確,你可以使用上面提供的工作職能,做好你的工作如下:

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. 
}