@abra-cadabra

Как загрузить прайс лист по частям?

Здравствуйте
Столкнулся с проблемой в реализации загрузки прайслиста в формате json. На моем сервер есть файл обработчик который принимает пост запрос с другого сервера, в запросе передается json массив данных. В этих данных есть как категории товаров так и сами товары с характеристиками. Я этот массив обрабатываю и заношу данные в БД, но при больших объемах данных все зависает напрочь. Как можно это оптимизировать или может как то разбивать этот массив данных на части.
  • Вопрос задан
  • 349 просмотров
Пригласить эксперта
Ответы на вопрос 4
webinar
@webinar Куратор тега PHP
Учим yii: https://youtu.be/-WRMlGHLgRg
Самый простой вариант, это реализовать на клиенте отправку частями. Обычно это удобно, так как кроме этого удобно и просто реализуется прогресбар.
Так же есть вариант с занесением json в файл или даже в БД лучше и обработку делать уже после, частями, если узкое место именно в обработке. В любом случае лучше вначале определить где узкое место.
Ответ написан
Комментировать
@Kravalg
Раз уж 504 ошибка, это значит, что сервер не успевает за отведенное ему время отдать ответ. Это и немудренно, так как ты при получении данных сразу же их обрабатываешь. Для малого количества данных этот подход уместен, но для больших - нет в чем ты уже убедился.

Решение, которые позволит тебе обрабатывать данные практически любых размеров:

1) Скрипт, который принимает данные и обрабатывает их сейчас должен сохранять их(к примеру, в файл) и ставить в очередь на обработку. Теперь твой скрипт не будет улетать в 504, так как ответ будет за считанные миллисекунды.
2) Следующим этапом будет написание скрипта, который будет получать сообщения из очереди на обработку этих данных. Если размер данных, которые ты получаешь исчисляется в сотнях мегабайтов и больше, тогда перед обработкой этих данных тебе необходимо будет их поделить на части (в случае, если хранилищем ты выберешь файлы).
3) После того, как ты получишь данные по частям ты можешь их обрабатывать в фоновом режиме

Я описал общий алгоритм, если не можешь выбрать конкретные технологии - пиши в комментарии, подскажу

UPD.
Для обработки больших файлов можно использовать генераторы - статья

Для запуска фоновых обработчиков можно использовать cron или workers - статья
Ответ написан
orlov0562
@orlov0562 Куратор тега PHP
I'm cool!
Нужно заняться отладкой и понять где возникает проблема, т.е. в чем причина зависания. Возможно, нужно просто выделить больше памяти для работы скрипта импорта. Попробуй писать лог из критичных мест скрипта и посмотри где скрипт зависает/падает.

--[дополнено]--

Ошибка 504 Gateway Timeout (time out), означает что веб-сервер не смог обработать данные в отведенные срок выполнения скрипта. Как написал уже Kravalg , тебе нужно в момент получения данных сохранить их в файл.

Затем запланировать задачу по импорту через крон без использования веб-сервера. Т.е. написать весь импорт в файле import.php который будет запускаться по крону без использования веб-сервера
(по типу /usr/bin/php import.php). Так твой скрипт импорта будет работать столько сколько надо.

Другой способ, это сообщить веб-серверу, что соединение закрыто, но продолжить выполнение твоего скрипта, примерно так
session_write_close(); // закрыть сессию
fastcgi_finish_request(); // завершить обработку запроса клиента 
.. // тут "долгие" операции

будет ли работать этот способ зависит от настроек твоего веб-сервера и php

по классике, делай по первому способу: сначало прием данных из вне и только сохранение в файл, затем обработка по крону. А еще лучше, загрузка+обработка по крону без участие веб сервера.

P.S. при обработке по крону, в 90% случаев ты можешь игнорировать ограничения по времени работы скрипта и кол-во памяти (смотри опции вызова бинарника php).
Т.е. ты легко можешь прочитать через json_decode(file_get_contents(..))
гигабайтный или более файл и потом еще час его обрабатывать так, как тебе надо...
Ответ написан
@abra-cadabra Автор вопроса
504 ошибка. Попросту обработчик получаемых данных на этапе внесения данных в БД зависает.
Там как бы прайс, в нем могут быть как новые товары, так и старые без изменений. Вот каждые товар которые в этом месива нужно проверить существует ли он уже в БД, и потоп есть ли изменения в цена и остатках. А этом все доп запросы. Вот и получается что примерно из 8К товаров импортируется от силы 2К до того момента пока все не зависает.

Данные которые мне отправляют не могут быть поделены, на стороне склада у них программист не хочет шевелится что бы что то менять под меня.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы