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

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

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

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

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

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

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

Но что-то мне подсказывает, что существует какое-то иное решение или лучшее понимание проблемы.
Заранее спасибо за подсказки.
  • Вопрос задан
  • 4466 просмотров
Решения вопроса 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) После закрытия транзакции — взять очередную порцию.
    Ответ написан
Ваш ответ на вопрос

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

Войти через TM ID
Похожие вопросы
Вакансии с Моего Круга Все вакансии
Заказы с Фрилансим Все заказы