Параллельная обработка в PHP с использованием zeroMQ

Небольшая предыстория: я создаю серверное приложение на php, которое должно выполнять ряд независимых задач по запросу пользователя. У моего приложения есть серьезные требования к скорости, поэтому я хотел бы выполнять все эти задачи параллельно.

Я рассмотрел несколько решений (например, gearman, rabbitMQ, zeroMQ) и решил использовать zeroMQ (быстро, с хорошей документацией, гибко и не требует брокера). Это решает проблему связи/синхронизации между потоками для меня.

Вопрос: я хотел бы инициировать задачи только тогда, когда сервер получает запрос (чтобы не было длительного процесса). Итак, я получаю запрос -> запустить параллельные вычисления -> вернуть результат вычислений клиенту. Одним из решений для этого кажется pcntl_fork, однако в документах упоминаются некоторые проблемы. с использованием его в среде производственного сервера, но на самом деле не указывает, что это такое?

Мой другой вариант - использовать proc_open, но мне он нравится меньше, потому что это потребует от меня сериализации входных данных каким-то образом, который кажется менее гибким и быстрым, чем разветвление. Есть ли у него преимущества перед pcntl_fork?

Есть ли другое решение (все еще использующее php: p)?


person roinir    schedule 06.08.2015    source источник
comment
Как вы, возможно, уже поняли, обработка PARALLEL — гораздо более сложная задача, чем специальное разветвление. [Хороший пост по этому поводу.][1] Вы можете переосмыслить, способна ли ваша архитектура соответствовать парадигме обработки PARALLEL или нет. В противном случае компоненты PHP/ZeroMQ не спасут этот основной сбой. Если да, то ZeroMQ необходимо настроить с особой тщательностью, чтобы он был готов к истинной обработке PARALLEL. [1]: stackoverflow.com/a/27347539/3666197   -  person user3666197    schedule 09.08.2015


Ответы (1)


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

Вы говорите, что у вас есть серьезные требования к скорости - вы подтвердили, что обычный однопоточный PHP недостаточно быстр? Проведите какие-нибудь бенчмарки, выяснили свои узкие места? Если ваши требования к скорости так велики, вы можете даже подумать об использовании другого языка, несмотря на все прелести PHP, он никогда не будет самым эффективным молотком в наборе инструментов. Java — хороший вариант для максимальной скорости, а node.js — хороший вариант, если ваши узкие места зависят от операций ввода-вывода. Меня больше всего беспокоит то, что в отсутствие дополнительной информации этот вопрос попахивает преждевременной оптимизацией. Это может быть несправедливо, и вы, возможно, опустили эти детали, потому что это не было сутью вашего вопроса, но как посторонний я, по крайней мере, хотел убедиться, что вы думаете об этих вещах, если вы еще этого не сделали.

Вы хотите избежать длительных процессов — почему? В длительных процессах нет ничего плохого по своей сути, но это ощущается неправильным, когда вы привыкли к псевдоэффективной природе Apache+mod_php "по требованию". Убедитесь, что вы не пытаетесь избежать чего-то только потому, что вы к этому не привыкли.

То, что вы, кажется, описываете, выполняет параллельную обработку из вашего веб-приложения PHP - точно так же, как и любая другая веб-страница, которую вы пишете, Apache инициирует ваш PHP-скрипт, этот скрипт разветвляет другой процесс и вместо того, чтобы выполнять свои действия последовательно, выполняет их в parallel, завершает работу и возвращает пользователю по завершении рендеринга страницы. Если это так, то вот ответ на ваш первоначальный вопрос:

Вы не можете использовать pcntl_fork из веб-процесса, только из командной строки. Подробности об этом находятся на странице, на которую вы ссылаетесь, внизу в комментариях:

Дело не в "нельзя", а в "нельзя". Несмотря на то, что я скомпилировал в PCNTL с помощью --enable-pcntl, оказалось, что он компилируется только в CLI-версию PHP, а не в модуль Apache. [...] function_exists('pcntl_fork') возвращал false, хотя скомпилировался правильно. Оказывается, он отлично возвращает true из CLI и возвращает false только для HTTP-запросов. То же самое верно для ВСЕХ функций pcntl_*().

... это означает, что либо вам придется инициировать процесс разветвления как отдельный длительный процесс, либо вам придется запускать его по запросу с помощью proc_open, нет никакого способа заставить его работать так, как я предполагаю вы этого хотите.

person Jason    schedule 07.08.2015
comment
Спасибо за ответ. Я пропустил этот комментарий в документации о pcntl. К счастью, наше текущее решение включает в себя сначала вызов proc_open и только потом разветвление. - person roinir; 07.08.2015
comment
@ Джейсон, большое спасибо за то, что снова упомянул преждевременную оптимизацию. Как постоянный читатель, я всегда нахожу там новые жемчужины. - person user3666197; 09.08.2015