Параллельная обработка в PHP – Как вы это делаете?

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

A. Многопоточность:

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

B. Многопроцессорный процесс:

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

  • Ветвление
  • Выполнение команд
  • кант

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

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

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

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

  • ZeroMQ (хороший вариант, сложный в использовании) ориентированная на сообщение библиотека IPC, является сервером очереди сообщений в Erlang, сохраняет задания в памяти. Это библиотека сокетов, которая выступает в качестве среды параллелизма. Быстрее, чем TCP для кластеризованных продуктов и суперкомпьютеров.
  • RabbitMQ (хороший вариант, простой в использовании) самостоятельно, корпоративные очереди сообщений, не рабочая очередь, а скорее очередь сообщений, которая может использоваться как рабочая очередь, но требует дополнительной семантики.
  • Beanstalkd (лучший вариант, простой в использовании) (встроенная поддержка Laravel, созданная facebook, для рабочей очереди) – есть «консольная консоль Beanstalkd», которая очень приятная
  • Gearman (проблема: централизованная брокерская система для распределенной обработки)
  • Apache ActiveMQ – самый популярный брокер сообщений с открытым исходным кодом в Java, (проблема: много ошибок и проблем)
  • Amazon SQS (поддерживается Laravel, Hosted – так что администрация не требуется). На самом деле, рабочая очередь не потребует дополнительной работы для обработки семантики, такой как захоронение задания)
  • IronMQ (встроенная поддержка Laravel, написанная в Go, доступна как в виде облачной версии, так и на месте)
  • Redis (Laravel встроен в поддержку, не так быстро, как он не предназначен для этого)
  • Воробей (написанный на Ruby, основанный на memcache)
  • Старлинг (написанный на Ruby, основанный на memcache, встроенный в твиттер)
  • Пустельга (всего лишь QM)
  • Кафка (написано в LinkedIn в Скале)
  • EagleMQ с открытым исходным кодом, высокопроизводительный и легкий менеджер очередей (написан на C)

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

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

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

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

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

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

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

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

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

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

Взгляните на этот пример – https://github.com/rakesh-sankar/Tools/blob/master/PHP/fork-parallel-process.php .

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

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

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

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

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

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

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

НТН

C.