Задания в очереди Laravel выполняются на много минут дольше таймаута

У меня есть задание в очереди Laravel, которое извлекает ссылки с веб-страницы. Тайм-аут для прослушивателя очереди, настроенного через Laravel Forge, составляет 240 секунд (4 минуты). Однако выполнение заданий занимает до 45 минут.

Мои настройки очереди:

'redis' => [
    'driver' => 'redis',
    'connection' => 'default',
    'queue' => 'default',
    'retry_after' => 350,
],

Кроме того, выполняется несколько рабочих процессов - до 35. Как вы понимаете, это съедает много памяти сервера. Кажется, что процессы просто зависают. Команда для этих процессов, показанная в top:

php7.1 artisan queue:work redis --once --queue=linkqueue --delay=0 --memory=128 --sleep=10 --tries=1 --env=local

Как можно выполнить задание в течение 45 минут, если время ожидания составляет 240 секунд? Почему существует так много процессов - разве не должен быть только один?

Кроме того, есть идеи, почему скрипт для извлечения ссылок должен запускаться за 45 минут ?!

Сценарий работает, то есть в большинстве случаев он работает должным образом - на это уходит много времени. Насколько я могу судить, ошибок нет.

Код в работе:

$dom = new DOMDocument;
$dom->loadHTML($html);
$links = $dom->getElementsByTagName('a');

foreach ($links as $a) {
    $link = $a->getAttribute('href');

    $newurl = new URL;
    $newurl->url = $link;
    $newurl->save();
}

Обновление: еще одно простое задание выполняется без проблем, менее чем за секунду. В частности, работа ссылки выше занимает 10 секунд. Может быть проблема с оперативной памятью или что-то в этом роде? Что еще я могу сделать для диагностики проблемы? При запуске в составе консольного задания сама функция извлечения ссылок выполняется за 1 или 2 секунды. Это пугает только в очереди.


person samiles    schedule 02.02.2017    source источник
comment
Вы пробовали запустить скрипт вручную и проверить сколько времени занимает? :)   -  person Troyer    schedule 02.02.2017
comment
@Troyer Да, извините, следовало упомянуть об этом - я не могу заставить это занять более 1-2 секунд, когда выйдет из очереди. Это очень быстро. Как будто скрипт блокируется / зависает при постановке в очередь. Конечно, это займет далеко не 45 минут!   -  person samiles    schedule 02.02.2017


Ответы (2)


Как можно выполнить задание в течение 45 минут, если время ожидания составляет 240 секунд?

Потому что у вас 'retry_after' => 350, в подключении к очереди. Это означает, что если Laravel не получает ответа от задания через 350 секунд - он предполагает, что задание завершилось неудачно, и повторяет попытку снова. Это приводит к нескольким процессам одного задания в вашей ситуации.

Если вы хотите, чтобы ваши задания выполнялись на срок до 45 минут, вам следует установить для retry_after большее число. Скажите 3600, что составляет 1 час.

Таким образом, задание будет запускаться только в том случае, если для его выполнения требуется более 1 часа.

person Laurence    schedule 06.05.2017

Вы также можете сделать следующее, чтобы сделать таймауты неограниченными.

php artisan queue:listen --timeout=0
person Nick Poulos    schedule 08.06.2017