Я работаю над функцией импорта данных для веб-сайта. Я использую Laravel 5.1 на ферме, и дал машине 4 ГБ оперативной памяти и два виртуальных процессора. Для импорта данных я использовал пакет Laravel Excel с его механизмом разбиения на фрагменты, который в основном разбивает набор данных на куски и добавляет обработку в очередь. Рабочий процесс для этого выглядит следующим образом:
Я установил очередь с именем ‘import’ в супервизоре для этих процессов. Наряду с этой очередью у меня также есть очередь по умолчанию (для отправки писем и других, менее интенсивных вещей) и очередь с низким приоритетом для отправки заданий из других заданий. Вот моя конфигурация супервизора:
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=/usr/bin/php /home/vagrant/Code/iris/artisan queue:work --tries=1 --daemon --queue=default,import,background1
autostart=true
autorestart=true
user=vagrant
numprocs=8
redirect_stderr=true
stdout_logfile=/home/vagrant/Code/iris/storage/logs/worker.log
С небольшими файлами это работает хорошо, но когда я пытаюсь импортировать документ размером ~ 30k, php-процессы, порожденные супервизором, исчерпывают память к концу, и в журнале laravel я вижу InvalidArgumentException: No handler registered for command [__PHP_Incomplete_Class] in Illuminate\Bus\Dispatcher
(это происходит, особенно когда я запускаю два импорта параллельно или пытаюсь загрузить что-либо через веб-сокеты), и я действительно не понимаю, почему это происходит. Насколько я могу судить по использованию memory_get_usage (), ни один процесс не превышает ограничение в 512 МБ. Это проблема сборщика мусора? Должен ли я вызвать его вручную?
И так как я упомянул веб-сокеты, я также пытался создать отдельную очередь (с более высоким приоритетом) для обработки запросов веб-сокетов. Я перепробовал несколько конфигураций супервизора (создал выделенного работника в файлах конфигурации супервизора, добавил очередь в опцию —queue = в конфигурации и т. Д.), Но безрезультатно. Я реализовал загрузку отчетов через веб-сокеты, и он сам по себе работает нормально, но когда в очереди есть другие вещи, запрос сокета обрабатывается после того, как несколько элементов в очереди «import» с более низким приоритетом завершают работу, что позволяет мне верить в то, что я выполняю не очень хорошо понимаю приоритеты очереди. Есть ли способ создать отдельную очередь для запросов сокетов, которая немедленно отвечает на эти запросы?
ОБНОВИТЬ
Я сузил утечку памяти до работы, которую мы отправляли в конце импорта. Однако я не могу отправить это задание при попытке импортировать очень большой файл (30 000+ строк). Это ошибки InvalidArgumentException: No handler registered for command [__PHP_Incomplete_Class] in Illuminate\Bus\Dispatcher
(Я думаю, это потому, что ему не хватает памяти), и процессы php, которые были запущены супервизором, остаются активными и, похоже, потребляют то же количество ресурсов, что и на пике (около 450 МБ каждый). Это продолжается, пока я не запускаю вручную php artisan queue:restart
, Для небольших файлов поток работает с намерением: он запускает пакеты Excel и в конце отправляет задание в очередь, которое также успешно обрабатывается.
Задача ещё не решена.
Других решений пока нет …