асинхронная обработка с PHP - один работник на задание - PullRequest
9 голосов
/ 18 августа 2010

Рассмотрим веб-приложение PHP, целью которого является принятие пользовательских запросов на запуск общих асинхронных заданий, а затем создание рабочего процесса / потока для запуска задания.Задания не особенно загружают процессор или память, но ожидается, что они будут блокировать вызовы ввода-вывода довольно часто.Не более одного или двух заданий должно запускаться в секунду, но из-за длительного времени может выполняться много заданий одновременно.

Поэтому крайне важно, чтобы задания выполнялись параллельно.Кроме того, каждая работа должна контролироваться демоном менеджера, ответственным за убийство зависших работников, прерывание работы рабочих по запросу пользователя и т. Д.

Как лучше всего внедрить такую ​​систему?Я вижу:

  1. Формирование работника из менеджера - кажется, это вариант самого низкого уровня, и мне пришлось бы самому внедрить систему мониторинга.Apache - это веб-сервер, поэтому, похоже, что для этой опции потребуется запуск любых работников PHP через FastCGI.
  2. Использование какой-либо очереди заданий / сообщений.(gearman, beanstalkd, RabbitMQ и т. д.) - изначально это казалось очевидным выбором.После некоторых исследований я несколько путаю все варианты.Например, Gearman выглядит так, как будто он разработан для огромных распределенных систем, в которых имеется фиксированный пул работников ... поэтому я не знаю, подходит ли он для того, что мне нужно (один работник на работу).

Ответы [ 3 ]

8 голосов
/ 18 августа 2010

Что ж, если вы работаете в Linux, вы можете использовать pcntl_fork, чтобы отключить детей. Затем «мастер» наблюдает за детьми. Каждый ребенок выполняет свою задачу и затем существует в обычном режиме.

Лично в моих реализациях мне никогда не требовалась очередь сообщений. Я просто использовал массив в «мастере» с блокировками. Когда ребенок получает работу, он записывает файл блокировки с идентификатором работы. Затем мастер будет ждать, пока этот ребенок не выйдет. Если файл блокировки все еще существует после выхода дочернего элемента, то я знаю, что задача не была выполнена, и повторно запустите дочерний элемент с тем же заданием (после удаления файла блокировки). В зависимости от вашей ситуации вы можете реализовать очередь в простой таблице базы данных. Вставьте задания в таблицу и проверяйте таблицу в мастере каждые 30 или 60 секунд на наличие новых заданий. Затем удаляйте их из таблицы только после того, как дочерний элемент закончил (и дочерний элемент удалил файл блокировки). Это может иметь проблемы, если у вас одновременно работает несколько «master», но вы можете реализовать глобальный «master pid файл» для обнаружения и предотвращения нескольких экземпляров ...

И я бы не советовал разветвляться с FastCGI. Это может привести к некоторым очень неясным проблемам, поскольку среда должна сохраняться. Вместо этого используйте CGI, если у вас должен быть веб-интерфейс, но в идеале используйте приложение CLI (демон). Для взаимодействия с мастером из других процессов вы можете использовать сокеты для связи по протоколу TCP или создать файл FIFO для связи.

Что касается обнаружения зависших работников, вы могли бы реализовать систему «сердцебиения», при которой ребенок выдает SIG_USR1 ведущему процессу каждые столько секунд. Тогда, если вы не слышали от ребенка в два или три раза за это время, он может быть повешен. Но дело в том, что PHP не многопоточный, вы не можете сказать, завис ли ребенок или он просто ожидает блокирующий ресурс (например, вызов базы данных) ... Что касается реализации "сердцебиения" Вы можете использовать тиковую функцию , чтобы автоматизировать сердцебиение (но имейте в виду, что блокировка вызовов по-прежнему не будет выполняться) ...

1 голос
/ 31 марта 2016

пока вы выполняете одну асинхронную задачу со многими заданиями с помощью pcntl_fork, или вы будете создавать постоянный запрос каждые (s) секунды, будьте осторожны с высоким энергопотреблением процессора, вы можете получить зависающую память обработки, потому что не можете снова выделить память, яПодумайте, какой лучший выбор вы можете создать полностью с Gearman, или вы можете попробовать с облачным рабочим, таким как IronWorker.

1 голос
/ 06 мая 2014
...