happyproff
@happyproff
Счастливый веб-разработчик

Распараллелить работу части скрипта?

Приветствую.


Прошу подсказки с таким моментом. Есть таск, который выполняется долго. В нём происходит общение с чужим API, которое и занимает большую часть времени. Алгоритм такой:

  1. Читаем из базы исходные данные, готовим и разбиваем на порции. Это довольно быстро.
  2. Итерируем массив порций, отправляем каждую в API, получаем ответ, пишем его в базу. А вот это очень медленно.
  3. Обрабатываем все полученные данные, пишем ещё и результат обработки. Это тоже довольно быстро.


Что бы ускорить выполнение этого таска, очевидно нужно отправлять порции данных в API параллельно, а не последовательно. Варианты, первыми пришедшие в голову:

  1. Gearman. Но, кажется, это что-то не совсем то или я не понимаю, как с ним работать. Мне не нужно просто сплавить работу воркерам, мне нужно запустить их именно параллельно и дождавшись результата работы всех воркеров, выполнить финальное действие. Может быть нужно добавить задачи как фоновые, а потом смотреть на список задач на job-сервере?
  2. pcntl_fork. Здесь не до конца понимаю принцип работы: в какой-то момент у меня есть массив довольно больших объектов. Мне нужно выполнить отправку частей этого массива с разными параметрами (разные реквизиты доступа к API, например). В таком случае, понадобится форкнуться нужное число раз, получить «приветы» от клонов, раздать им данные и ждать от каждого ответа? Или я всё усложняю?
  3. Ещё думал дожидаться завершения работы потомков по каким-нибудь .pid файлам.


Но что-то мне подсказывает, что существует какое-то иное решение или лучшее понимание проблемы.

Заранее спасибо за подсказки.
  • Вопрос задан
  • 4811 просмотров
Решения вопроса 1
sajgak
@sajgak
Gearman как раз то. Он поддерживает паралельный запуск задач и получение ответа по завершению (aka callback) через методы (doNormal, doHigh, doLow).
С форками работать сложнее, но тоже можно. Для каждой итерации вы форкаете новый процесс и записываете куда то результат, вопрос только в том, как потом общий результат прочитать. В общем я бы вам посоветовался поближе разобраться с gearman
Ответ написан
Пригласить эксперта
Ответы на вопрос 4
Urvin
@Urvin
2. pcntl_signal даст сигнал об окончании работы дочернего процесса.
Когда работал с этими функциями долго не мог врубиться в совершенно теские вещи. Работа идет примерно так:
а) Вешаем обработчик pcntl_signal. Это сигнал об окончании какого-то из процессов.
б) Циклично форкаемся, предварительно записывая в некую переменную номер пакета данных. По справке определяем — копия/не копия.
в) если копия, posix_setsid, деаем нужный код или через pcntl_exec замещаем себя обработчиком пакета.
В этом месте обработчик пакета принимает возвращенные сторонним сервисом данные и как-либо их обрабатывает.
г) По завершении работы дочернего процесса мы знаем его PID и, соответвенно, знаем индекс обработанного пакет.

3. ps x и читаем вывод. Знаем PID и прочие атрибуты процессов. Но некошерно.
Ответ написан
javax
@javax
Software Architect, Java Developer since 1996
Не знаю, насколько это актуально для Вас, но я такого типа скрипты пишу на Groovy
Там можно и треды запустить для параллельной работы
Ответ написан
strib
@strib
Смотря как лежат данные.
Если в БД и включены транзакции, то я бы сделал так.
1) Форкнулся необходимое количество раз.
2) Транациями брал из базы набор записей и обрабатывал. Записи были бы блокированы. Ну или анонимной транзакцией помечал как исполняемые (хз можно ли в MySQL так сделать)
3) После закрытия транзакции — взять очередную порцию.
Ответ написан
Очень крутой фреймворк для async приложений на php — reactphp.org
Ответ написан
Ваш ответ на вопрос

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

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