асинхронное выполнение задач для веб -приложения

StackOverflow https://stackoverflow.com/questions/1748413

  •  20-09-2019
  •  | 
  •  

Вопрос

Веб -приложение, которое я разрабатываю, необходимо выполнять задачи, которые слишком длинные, чтобы выполнять во время цикла HTTP -запроса/ответа. Как правило, пользователь будет выполнять запрос, сервер будет принимать этот запрос и, среди прочего, запустить некоторые сценарии для генерации данных (например, изображения с Povray).

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

Теперь мой вопрос не относится к дизайну (хотя я также очень наслаждаюсь намеками на этот счет). У меня вопрос: существует ли система для решения этой проблемы, поэтому я не переосмысливаю квадратное колесо? Если бы мне пришлось, я бы использовал диспетчер процессов очередей, чтобы отправить задачу и поместить конечную точку HTTP, чтобы выпустить статус, что -то вроде «ожидаемого», «прерванного», «завершено» клиенту Ajax, но если что -то уже что -то подобное уже Существует конкретно для этой задачи, я бы в основном наслаждался этим.

Я работаю в Python+Django.

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

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

Редактировать 2: Я добавил щедрость, чтобы увидеть, смогу ли я получить какой -нибудь другой ответ. Я проверил пироптинг, но я не могу выполнить работу работы и воссоединиться с очередью на более позднем этапе.

Это было полезно?

Решение

Вы должны избегать повторного изобретения колеса здесь.

Проверить Gearman. Анкет Он имеет библиотеки на многих языках (включая Python) и довольно популярен. Не уверен, что у кого -нибудь есть какие -либо способы легко подключить Django к вызовам Gearman и Ajax, но не должно быть сложно сделать эту часть самостоятельно.

Основная идея состоит в том, что вы запускаете сервер заданий Gearman (или несколько серверов заданий), вы запускаете задачу (например, «resize_photo») с некоторыми аргументами (например, '{photo_id: 1234}'). Вы стоят в очереди как фоновую задачу. Вы получите ручку обратно. Затем ваш запрос AJAX собирается опросить на этом значении ручки, пока он не будет помечен как завершенное.

Тогда у вас есть работник (или, вероятно, многие), который является отдельным процессом Python, подключающимся к этому серверу заданий и регистрируется для заданий RESIFIZE_PHOTO ', выполняет работу, а затем отмечает его как полную.

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

Другие советы

Вы можете попробовать два подхода:

  • К Позвоните WebServer каждый не интервал и информировать удостоверение личности; Сервер процессы и возвращает некоторую информацию о текущем выполнении этой задачи
  • Для реализации давней подрядной страницы, отправка данных каждый не интервал; Для клиента этот HTTP -запрос будет «всегда» будет "loading" И необходимо собирать новую информацию каждый раз, когда получает новую часть данных.

О втором варианте, вы можете узнать больше, прочитав о Комета; Используя asp.net, вы можете сделать что -то подобное, реализовав System.web.ihttpasynchandler интерфейс.

Я не знаю системы, которая делает это, но было бы довольно легко внедрить собственную систему:

  • Создайте таблицу баз данных с Jobid, JobParameters, JobResult
    • JobResult - это строка, которая будет иметь маринованный результат
    • JobParameters - это маринованный список входных аргументов
  • Когда сервер начинает работать над заданием, он создает новую строку в таблице, и Spwans новый процесс, чтобы справиться с этим, передавая этот процесс Jobid
  • Обработчик задач обновляет JobResult в таблице, когда она закончена
  • Веб -страница (xmlrpc или что -то, что вы используете) содержит метод «getResult (jobid)», который проверит таблицу для JobResult
    • Если он находит результат, он возвращает результат и удаляет строку из таблицы
    • В противном случае он возвращает пустой список, или нет, или ваше предпочтительное возвратное значение, чтобы сигнализировать о том, что задание еще не закончено

Существует несколько краев, чтобы позаботиться, так что существующая структура явно была бы лучше, как вы говорите.

Сначала вам нужна отдельная услуга «работника», которая будет начата отдельно в Powerup и сообщается с помощью HTTP-рекордных обработчиков через некоторые локальные МПК, такие как Unix-Socket (Fast) или база данных (просто).

Во время обработки запроса CGI спрашивайте из состояния работника или других данных и воспроизведение клиенту.

Вы можете сигнализировать о том, что ресурс «работает над», отвечая на код HTTP 202: стороне клиента придется повторить позже, чтобы получить завершенный ресурс. В зависимости от случая, вам, возможно, придется выпустить «идентификатор запроса», чтобы соответствовать запросу с ответом.

В качестве альтернативы, вы можете взглянуть на существующие библиотеки кометы, которые могут удовлетворить ваши потребности больше «из коробки». Я не уверен, есть ли что -то, что соответствует вашему текущему дизайну Django.

Вероятно, не отличный ответ для решения Python/Django, с которым вы работаете, но мы используем очередь сообщений Microsoft для таких вещей, как это. Это в основном работает так

  1. Обновления веб -сайта в строке базы данных где -то со статусом «обработки»
  2. Веб -сайт отправляет сообщение MSMQ (это не блокирующий звонок, поэтому он сразу возвращает контроль на веб -сайте)
  3. Служба Windows (может быть любой программой на самом деле) - «смотреть» MSMQ и получает сообщение
  4. Служба Windows обновляет строку базы данных со статусом «законченного».

В любом случае это суть этого. Это было довольно надежно для нас и действительно просто для масштабирования и управления.

-ал

Еще один хороший вариант для Python и Django - это Сельдерей.

И если вы думаете, что сельдерей слишком тяжелый для ваших нужд, то вы можете посмотреть на простые распределенные TaskQueue.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top