Параллельная обработка в PHP - Как вы это делаете? - PullRequest
32 голосов
/ 24 мая 2011

В настоящее время я пытаюсь реализовать очередь заданий в php.Затем очередь будет обрабатываться как пакетное задание и должна иметь возможность обрабатывать некоторые задания параллельно.

Я уже провел какое-то исследование и нашел несколько способов его реализовать, но я не очень осведомлен об их преимуществах и недостатках.

Например, выполняя параллельную обработку, вызывая скрипт несколько раз через fsockopen, как описано здесь:
Простая параллельная обработка в PHP

Другой способ, который я нашел, былиспользуя функции curl_multi.
curl_multi_exec PHP docs

Но я думаю, что эти два способа значительно увеличат накладные расходы на создание пакетной обработки в очереди, хотя в основном они должны выполняться в фоновом режиме?

Я также читал о pcntl_fork, который также является способом решения проблемы.Но похоже, что это может стать очень грязным, если вы действительно не знаете, что делаете (как я в данный момент;)).

Я также посмотрел на Gearman, но там я быТакже необходимо динамически порождать рабочие потоки по мере необходимости, а не просто запускать несколько и позволить серверу заданий gearman затем отправить его свободным работникам.Особенно потому, что потоки должны завершаться без ошибок после выполнения одного задания, чтобы не допустить возможных утечек памяти (код может быть не идеален в этом вопросе).
Gearman Начало работы

Итак, мой вопрос, как вы обрабатываете параллельную обработку в PHP?И почему вы выбираете свой метод, какие преимущества / недостатки могут иметь различные методы?

Спасибо за любой вклад.

Ответы [ 7 ]

16 голосов
/ 24 мая 2011

я использую exec().Это легко и чисто.По сути, вам нужно построить менеджер потоков и скрипты потоков, которые будут делать то, что вам нужно.

Мне не нравится fsockopen(), потому что это откроет соединение с сервером, которое будет накапливаться и может ударить по соединению apachelimit

Мне не нравятся curl функции по той же причине

Мне не нравится pnctl, потому что для этого требуется доступное расширение pnctl, и вы должны следить за родительскими / дочерними отношениями.

никогда не играл с редуктором ...

7 голосов
/ 06 апреля 2016

Ну, я думаю, у нас есть 3 варианта:

A. Multi-Thread:

PHP изначально не поддерживает многопоточность. Но есть одно расширение PHP (экспериментальное), называемое pthreads (https://github.com/krakjoe/pthreads)), которое позволяет вам сделать это.

B. Multi-процесс:

Это можно сделать тремя способами:

  • ветвление
  • Выполнение команд
  • 1022 * Трубы *

C. Распределенная параллельная обработка:

Как это работает:

  1. Приложение Client отправляет данные (сообщение AKA) «может быть отформатировано в JSON» в Engine (MQ Engine) «может быть локальным или внешним веб-сервисом»
  2. MQ Engine хранит данные «в основном в памяти и, возможно, в базе данных» внутри очередей (вы можете определить имя очереди)
  3. Приложение Client запрашивает у MQ Engine данные (сообщения) для их обработки в порядке (FIFO или на основе приоритета) «вы также можете запрашивать данные из определенной очереди».


Некоторые двигатели MQ:

  • ZeroMQ (хороший вариант, сложный в использовании) ориентированная на сообщения библиотека IPC, сервер очереди сообщений в Эрланге, хранит задания в памяти. Это библиотека сокетов, которая действует как среда параллелизма. Быстрее, чем TCP для кластерных продуктов и суперкомпьютеров.
  • RabbitMQ (хороший вариант, простой в использовании) Самостоятельно размещенные, Enterprise Message Queues, На самом деле не рабочая очередь, а скорее очередь сообщений, которая может использоваться в качестве рабочей очереди, но требует дополнительной семантики.
  • Beanstalkd (лучший вариант, прост в использовании) (Встроенная поддержка Laravel, созданная Facebook, для рабочей очереди) - имеет инструмент "Beanstalkd console", который очень хорош
  • Gearman (проблема: централизованная брокерская система для распределенной обработки)
  • Apache ActiveMQ самый популярный брокер сообщений с открытым исходным кодом в Java (проблема: много ошибок и проблем)
  • Amazon SQS (Встроенная поддержка Laravel, Хостинг - поэтому администрирование не требуется. На самом деле не рабочая очередь, поэтому потребуется дополнительная работа для обработки семантики, например, похороны работы)
  • IronMQ (Встроенная поддержка Laravel, Written in Go, Доступна как в облачной версии, так и локально)
  • Redis (Встроенная поддержка Laravel, не такая быстрая, как она не предназначена для этого)
  • Sparrow (написано на Ruby, основанном на memcache)
  • Старлинг (написано на Ruby, основанном на memcache, встроенном в твиттер)
  • Kestrel (просто еще один QM)
  • Кафка (Написано в LinkedIn в Scala)
  • EagleMQ высокопроизводительный и легкий менеджер очередей с открытым исходным кодом (написанный на C)

Больше их можно найти здесь: http://queues.io

3 голосов
/ 24 мая 2011

Если ваше приложение будет работать в среде unix / linux, я бы посоветовал вам воспользоваться опцией разветвления.Это в основном детская игра, чтобы заставить ее работать.Я использовал его для менеджера Cron, и у меня был код для возврата к дружественному к Windows пути к коду, если разветвление не было вариантом.

Варианты запуска всего сценария несколько раз, как вы заявляете, добавляют довольнонемного накладных расходов.Если ваш скрипт маленький, это может не быть проблемой.Но вы, вероятно, привыкнете выполнять параллельную обработку в PHP так, как хотите.И в следующий раз, когда у вас будет работа, которая использует 200 МБ данных, это вполне может стать проблемой.Так что вам лучше научиться тому, как можно придерживаться.

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

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

2 голосов
/ 24 мая 2011

Я использую PHP pnctl - это хорошо, если вы знаете, что делаете.Я понимаю вашу ситуацию, но я не думаю, что это что-то сложное для понимания нашего кода, мы просто должны быть немного более осознанными, чем когда-либо, при реализации очереди JOB или параллельного процесса.

Я чувствую, пока вы его кодируетеи убедитесь, что поток идеален вне курса, вы должны помнить ПАРАЛЛЕЛЬНЫЙ ПРОЦЕСС при реализации.

Где вы можете делать ошибки:

  1. Петли - должны быть в состоянии справитьсяGLOBAL VARS.
  2. Обработка некоторого набора транзакций - опять же, если вы правильно определите наборы, вы сможете выполнить это.

Посмотрите на этот пример - https://github.com/rakesh-sankar/Tools/blob/master/PHP/fork-parallel-process.php.

Надеюсь, это поможет.

2 голосов
/ 24 мая 2011

Я предпочитаю exec () и gearman. exec () прост и не требует подключения и требует меньше памяти. Механик должен иметь разъем, а рабочий должен занимать память. Но gearman более гибкий и быстрый, чем exec (). И самое главное, что он может развернуть работника на другом сервере. Если работа требует много времени и ресурсов. Я использую gearman в моем текущем проекте.

1 голос
/ 08 мая 2018

Ниже приведено краткое описание нескольких вариантов параллельной обработки в PHP.

AMP

Оформление заказа Amp - Асинхронный параллелизм стал проще - похоже, это самая зрелая библиотека PHP, которую я видел для параллельной обработки.

Класс процесса Peec

Этот класс был опубликован в комментариях PHP-функции exec () и предоставляет действительно простую отправную точку для разветвления новых процессов и отслеживания их.

Пример:

// You may use status(), start(), and stop(). notice that start() method gets called automatically one time.
$process = new Process('ls -al');

// or if you got the pid, however here only the status() metod will work.
$process = new Process();
$process.setPid(my_pid);

// Then you can start/stop/check status of the job.
$process.stop();
$process.start();
if ($process.status()) {
    echo "The process is currently running";
} else {
    echo "The process is not running.";
}

Сравнение других параметров

Также есть отличная статья Асинхронная обработка или многозадачность в PHP , которая объясняет плюсы и минусы различных подходов:

Швейцар

Затем, есть также это простое учебное пособие , которое было свернуто в небольшую библиотеку под названием Швейцар .

Надеюсь, что эти ссылки станут полезной отправной точкой для дальнейших исследований.

1 голос
/ 24 мая 2011

Метод, описанный в разделе «Простая параллельная обработка в PHP», совершенно пугающий - принцип в порядке - но реализация ???Как вы уже отметили, curl_multi_ fns обеспечивают гораздо лучший способ реализации этого подхода.

Но я думаю, что эти 2 способа добавят довольно много накладных расходов

Давам, вероятно, не нужен клиентский и серверный HTTP-стек для передачи задания - но если вы не работаете в Google, ваше время разработки будет намного дороже, чем ваши аппаратные средства - и есть много инструментов для управления HTTP /анализ производительности - и есть определенный стандартный материал, такой как уведомления о состоянии и аутентификация.

Многое от того, как вы реализуете решение, зависит от требуемого уровня целостности транзакций и от того, требуется ли вам обработка заказов.

Из упомянутых вами подходов я бы рекомендовал сосредоточиться на методе HTTP-запроса, используя curl_multi_.Но если вам нужен хороший транзакционный контроль / для доставки заказов, вам обязательно нужно запустить демон посредника между источником сообщений и агентами обработки (есть хорошо написанный однопоточный сервер, подходящий для использования в качестве платформы для посредника здесь ).Обратите внимание, что агенты обработки должны обрабатывать одно сообщение за один раз.

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

HTH

C.

...