#laravel #laravel-queue
#laravel #laravel-очередь
Вопрос:
У нас есть задание MyPrettyJob
, которое ставится в очередь через redis с контроллера. Когда мы запускаем это задание из команды, подобной so, задание выполняется успешно. Когда мы запускаем задание с небольшим количеством данных, очередь остается в сети, но когда мы запускаем задание с большим количеством данных, очередь вылетает с кодом выхода 12, что указывает на ошибку «Не хватает памяти».
Большое задание обрабатывает около 300 000 элементов, которые в основном зависят друг от друга. С этой целью мы не можем разделить это задание, не оказывая серьезного влияния на производительность. В некоторых крайних случаях это может занять до нескольких часов вместо нескольких минут, которые он занимает в настоящее время.
Для большого задания очередь выводит следующее:
$ php artisan queue:work --queue=myqueue
Processing: AppJobsMyPrettyJob
Processed: AppJobsMyPrettyJob
$ echo $?
12
Работник очереди даже вылетает, независимо от того, находится ли что-то в очереди за этим заданием. Это, по-видимому, предполагает, что сбой очереди происходит из-за очистки большого задания, но, похоже, это не дает никаких указаний на то, что это такое. Работник очереди также выходит из строя независимо от того, выполняются ли какие-либо взаимодействия с базой данных, что определяет все, что связано с базой данных.
Что делает очередь между заданиями? Могу ли я каким-либо образом отладить причину нехватки памяти после завершения задания? Может быть, очередь записывает что-то в журнал или что-то делает в redis между заданиями? Кажется, что это действительно странное время для сбоя этого процесса.
Комментарии:
1. помещайте данные в очередь порциями, чтобы избежать нехватки памяти
2. На самом деле мы не можем обойтись без огромного (в порядке часов) штрафа за накладные расходы.
3. @Sumurai8 Какое действие выполняет задание?
4. Он обрабатывает около 300 000 элементов, которые необходимо поместить в базу данных после просмотра набора данных. Поскольку большинство элементов зависят от других элементов, наиболее эффективный способ сделать это — сохранить все данные в памяти. Поскольку 300 000 обновлений занимают много времени, мы откладываем любые взаимодействия с базой данных до самого конца этого задания. Очередь вылетает независимо от того, выполняем ли мы взаимодействие с базой данных, но задание выполняется успешно в любом случае. Я полагаю, это означает, что он достигает конца метода обработки задания.
5. Очередь также вылетает независимо от того, поставлено ли что-либо еще в очередь после нее. Я полагаю, это означает, что это происходит во время очистки этого задания.
Ответ №1:
Код выхода 12 происходит, когда система queue worker определяет, что она использовала больше памяти, чем разрешено (см. https://github.com/laravel/framework/blob/5.8/src/Illuminate/Queue/Worker.php#L199-L210 для конкретного раздела кода). Если вы запускаете php artisan queue:work --memory=<digit>
там, где памяти достаточно для полного выполнения вашего задания (например, 1024 для 1 ГБ), вы должны иметь возможность разрешить выполнение вашего задания и продолжить выполнение после факта.