Лучшее решение для выполнения нескольких интенсивных заданий в определенное время - PullRequest
1 голос
/ 16 января 2012

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

Каждое из этих «заданий» хранится в БД MySQL с отметкой времени, когда задание должно быть запущено (могут быть месяцы в будущем). Задания могут быть отменены пользователем в любое время.

Проблема заключается в том, что установление IMAP-соединений является медленным процессом, и перед тем, как вставить сообщение, нам часто приходится условно проверять, есть ли ответ от кого-либо в папке «Входящие» (или аналогичный), что добавляет значительную нагрузку на обработку для каждого задания. .

В настоящее время у нас есть система, в которой у нас запускается скрипт cron каждую минуту или около того, который получает все задания из БД, которые необходимо выполнить в течение следующих X минут. Затем он разделяет их на пакеты заданий Z и для каждого пакета выполняет асинхронный запрос POST обратно на тот же сервер со всеми данными для этих заданий Z (для достижения «ложной» многопоточности). Затем сервер обрабатывает каждую партию заданий Z, которые поступают через HTTP.

Причина, по которой мы используем асинхронный HTTP POST для многопоточности, а не что-то вроде pnctl_fork, заключается в том, что мы можем добавлять другие серверы и вместо этого отправлять им POST-данные, а также запускать задания вместо текущего сервера.

Итак, мой вопрос - есть ли лучший способ сделать это?

Я ценю рабочие очереди, такие как beanstalkd , доступные для использования, но соответствуют ли они модели запуска заданий в определенное время?

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

Я уверен, что есть лучшие способы достичь того, что нам нужно - любые предложения будут высоко оценены!

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

1 Ответ

0 голосов
/ 23 января 2012

Beanstalkd будет разумным способом сделать это.Он имеет концепцию put-with-delay, поэтому вы можете регулярно заполнять очередь из вашего основного хранилища сообщением, которое можно будет зарезервировать и запускать за X секунды (время, когда вы хотите, чтобы -время).

Затем рабочие будут работать в обычном режиме, подключаясь к демону beanstalkd и ожидая, когда будет зарезервировано новое задание.Это также было бы намного эффективнее без использования HTTP-соединения.В качестве примера я использовал для отправки сообщений в Amazon SQS (по http).Это едва ли может сделать 20 QPS самое большее, но Beanstalkd принимал более тысячи в секунду практически без усилий.

Отредактировано, чтобы добавить: Вы не можете удалить работу, не зная ее IDхотя вы могли бы хранить это снаружи.ОТО, пользователи должны иметь возможность удалять задания в любое время до последней минуты?Вам не нужно помещать задание в очередь за несколько недель или месяцев, поэтому у вас по-прежнему будет только один DB-ридер, который запускается каждые, скажем, от 1 до 5 минут, чтобы поместить следующие несколько заданий в очередь, ипо-прежнему есть столько работников, сколько вам нужно, с эффективностью, которую они могут принести.

В конечном счете, это зависит от количества операций чтения / записи в БД, которые вы выполняете, и от того, как сервер баз данных может их обрабатывать..

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

...