Подтвердить что ты не робот

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

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

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

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

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

а. Multi-Thread:

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

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

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

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

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

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

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


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

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

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

Ответ 3

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

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

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

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

Ответ 4

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

Ответ 5

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

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

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

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

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

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

Ответ 6

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

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

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

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

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

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

НТН

С.