многопоточность PHP, MySQL - PullRequest
       4

многопоточность PHP, MySQL

2 голосов
/ 30 января 2011

У меня есть PHP-скрипт, который я использую, чтобы сделать около 1 мил. запросы каждый день к определенному веб-сервису.

Проблема в том, что в «нормальном» рабочем процессе скрипт работает почти весь день, чтобы завершить работу. Поэтому я работал над дополнительным компонентом. По сути, я разработал сценарий, который обращается к основному сценарию с помощью запроса multi-curl GET для генерации некоторого случайного значения tempid для каждых 500 записей и, наконец, выполняет другой запрос multi-curl, используя POST со всеми сгенерированными темпами. Однако я не чувствую, что это правильный путь, поэтому я хотел бы, чтобы некоторые советы / решения добавили возможности многопоточности в основной скрипт без использования дополнительных / внешних приложений (например, скрипт curl, который я сейчас использую). Вот основной сценарий: http://pastebin.com/rUQ6pwGS

Ответы [ 2 ]

1 голос
/ 30 января 2011

Это фоновый процесс, верно?В этом случае вы не должны запускать его через веб-сервер.Запустите его из командной строки, либо как демон, либо как задание cron.

Я предпочитаю задание "cron", потому что вы автоматически получаете автоматический перезапуск.Убедитесь, что у вас не запущено больше экземпляров программы, чем хотелось бы (это можно сделать, заблокировав файл в файловой системе, сделав что-то атомарное в базе данных и т. Д.).

Тогда вам просто нужно запуститьколичество процессов, которые вы хотите, и чтобы они считывали работу из очереди.

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

CREATE TABLE sometasks (
   ID of some kind,
   Other info required to do task,
   some data we need to know if the task is due yet or complete,
   locked_by_host VARCHAR(64) NULL,
   locked_by_pid INT NULL
)

Затем процесс выполнит следующий псевдо-запрос, чтобы заблокировать набор задач (размер пакета batch_size может быть равен 1)

UPDATE sometasks SET locked_by_host=my_hostname, locked_by_pid=my_pid 
  WHERE not_done_already AND locked_by_host IS NULL ORDER BY ID LIMIT batch_size

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

Я бы выбрал работу cron с процессом контроллера, который запускает N дочерних процессов и контролирует их.Дочерние процессы могут периодически умирать (помните, что PHP не имеет хорошего GC, поэтому он может легко вытекать из памяти) и перезапускаться для предотвращения утечек ресурсов.

Если работа завершена, родитель может выйти и ждатьбыть повторно вызванным cron (следующий час или что-то в этом роде).

NB: locked_by_host может хранить имя хоста (pids не уникальны на разных хостах) для обеспечения распределенной обработки, но, возможно, вам не нужноэто, так что вы можете опустить его.

Вы можете сделать этот дизайн более надежным, поместив столбец locked_time и определив, когда задача занимает слишком много времени - вы можете предупредить, убить процесс и попробовать еще раз или что-то еще.

1 голос
/ 30 января 2011

Если вы хотите сделать все правильно, вам следует установить очередь сообщений.Я предпочитаю redis , потому что это «сервер структуры данных, поскольку ключи могут содержать строки, хэши, списки, наборы и отсортированные наборы».Redis также очень fast .

Использование blpop (порождает пару рабочих потоков, использующих php <yourscript> для одновременной обработки работы) для прослушивания новых сообщений (работа) и rpush для добавления новых сообщений в очередь. Процессы порождения являются дорогими (относительными), и при использовании очереди сообщений это должно быть сделано только один раз при создании процесса .

Я бы пошел на phpredis , если бы вы могли (нужно перекомпилировать PHP), потому что это расширение написано на C и поэтому будет намного быстрее, чем клиенты на чистом PHP.Еще PRedis также является довольно зрелой библиотекой, которую вы могли бы использовать.

Вы также можете использовать этот brpop / rpush в качестве своего рода блокировки (если вам нужно).Это связано с тем, что:

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

Я бы посоветовал вам посмотреть в руководстве по повторному использованию Саймона , чтобы получить представление о полной силе, которую предлагает Redis.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...