Как обрабатывать несколько процессов PHP на нескольких серверах, чтобы запускаться только тогда, когда есть работа, и спать, когда нечего делать? - PullRequest
0 голосов
/ 28 декабря 2011

У меня есть вызов, который, кажется, мне не хватает. Я работаю над приложением, которое генерирует отчеты (большой анализ из базы данных, но здесь это не актуально). У меня есть 3 идентичных сценария, которые я называю «сценарии процесса».

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

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

Сначала я просто случайно выбрал «сценарий процесса», и у них у всех своя очередь. Однако теперь я вижу, что в некоторых случаях один сценарий процесса имеет очередь часов, а два других ничего не делают. Просто потому, что им посчастливилось не создавать очень большие отчеты, поэтому мне нужны более справедливые решения, чтобы одинаково сбалансировать работу.

Как я могу это сделать? Есть очередь, в которой могут работать несколько сценариев?

PS Я использую set_time_limit (0); для этих сценариев, и все они в настоящее время находятся в цикле while () и sleep (5) все время ...

Ответы [ 2 ]

2 голосов
/ 28 декабря 2011

Нет, нет, нет.

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

Я не хочу, чтобы эти скрипты постоянно находились в базе данных

СУБД обеспечивают отличную поддержку одновременного доступа.И хотя при выполнении операции с БД возникают накладные расходы, она очень мала по сравнению с объемом работы, который будет генерировать каждый запрос.Это также очень удобный субстрат для управления очередью заданий.

у них всех есть своя очередь

Почему?использование общей очереди по принципу «первым пришел - первым обслужен» обеспечит наилучшее использование ресурсов.

Сначала я просто случайно выбрал «сценарий процесса»

Это позволит равномерно распределить работу с очень большим количеством заданий и хорошим генератором случайных чисел.Один из подходов заключается в разделении данных (например, экземпляр 1 выбирает задания, где mod (job_number, number_of_instances) = 0, экземпляр выбирает задания, где mod (job_number, number_of_instances) = 1 ....) - но даже тогда это ненаилучшее использование доступных ресурсов.

все они в данный момент находятся в цикле while () и sleep (5) все время

Нет - это тоже неправильно.

Неэффективно, чтобы экземпляры постоянно опрашивали пустую очередь - поэтому вы реализуете план back-ofr, например,

$maxsleeptime=100;
$sleeptime=0;
while (true) {
   $next_job=get_available_job_from_db_queue();
   if (!$next_job) {
      $sleeptime=min($sleeptime*2, $maxsleeptime);
      sleep($sleeptime);
   } else {
      $sleeptime=0;
      process_job($next_job);
      mark_job_finished($next_job);
   }
}

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

1 голос
/ 28 декабря 2011

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

Он поставляется с отличным расширением PHP и очень хорошо задокументирован. Большинство примеров тоже на PHP, хотя он прозрачно работает и с другими языками.

http://gearman.org/

...