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

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

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


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

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


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

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


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

Заранее спасибо за подсказки.
  • Вопрос задан
  • 4655 просмотров
Решения вопроса 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
Ответ написан
Ваш ответ на вопрос

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

Войти через TM ID
Похожие вопросы
Zaymigo Нижний Новгород
от 20 000 до 100 000 руб.
Devmasterz Тюмень
от 80 000 до 120 000 руб.
18 июля 2018, в 22:20
4000 руб./за проект
18 июля 2018, в 21:54
1000 руб./в час