Обработка заданий через веб-приложение: обновления статуса в реальном времени и бэкэнд-сообщения
Я хотел бы реализовать (с открытым кодом) веб-приложение, где пользователь отправляет какой-то запрос через свой браузер для веб-приложения Python. Данные запроса используются для определения и отправки какого-либо тяжелого вычислительного задания. Вычислительные задания передаются на аутсорсинг в "рабочий сервер" (также Python). Во время обработки задания задание проходит различные этапы с течением времени (от "представленного" через промежуточные состояния до "готового", в идеале). Что я хотела сделать-показать текущее состояние задания пользователю в режиме реального времени. Это означает, что рабочий сервер должен передавать состояния задания обратно в веб-приложение. Затем веб-приложение должно передать информацию в браузер пользователя. Я принес для вас картину, которая схематично описывает основную идею:
цифры в красных кругах указывают на хронологический порядок событий. "веб-приложение" и "рабочий сервер" еще предстоит разработать. Теперь, я был бы признателен, если вы можете помочь мне с некоторыми технологические решения.
мои вопросы, в частности:
какую технологию обмена сообщениями следует применять между веб-приложением и рабочим сервером? Когда рабочий сервер выдает сигнал (какое-то сообщение) об определенном задании, он должен вызвать какое-то событие в веб-приложении. Следовательно, мне нужен какой-то обратный вызов, связанный с клиентом, который изначально запросил представление задания. Я думаю, мне нужен какой-то механизм pub/sub здесь, где рабочий сервер публикует, а веб-приложение подписывается. Когда веб-приложение получает сообщение, оно реагирует на него, отправляя клиенту обновление состояния. Я хочу, чтобы рабочий сервер был масштабируемым и сильно отделенным от веб-приложения. Поэтому я думал об использовании Redis или ZeroMQ для этой задачи. А ты как думаешь? Мой подход слишком сложен?
какую технологию следует использовать для передачи информации в браузер? Просто из перфекционизма я хотел бы иметь обновления в реальном времени. Я не хочу проводить опросы с высокой частотой. Я хочу немедленно нажать на клиента, когда рабочий сервер выдает сообщение : -). Кроме того, мне не нужна максимальная поддержка браузера. Этот проект, прежде всего, является более или менее techdemo для меня. Должен ли я перейти на HTML5 server-sent events / websockets? Или вы бы рекомендовали иначе?
большое большое спасибо за ваши рекомендации заранее.
3 ответов
чтобы быть полезным, ваше веб-приложение будет иметь базу данных. Я бы создал таблицу в этой базе данных, которая специально для этих заданий. У вас будет "штат" для каждой работы.
это упрощает вашу систему, потому что вы можете просто отправить свой запрос на запуск задания и передать его бэкэнд-работникам (zmq-хорошее решение для этой IMO). Поскольку вы используете python для back-end, очень тривиально заставить ваши рабочие задания либо обновить текущее рабочее задание в базе данных или иметь другой "updater", единственной задачей которого является обновление полей в базе данных (сохранение логики отдельно сделает для лучшего решения, позволяет вам, возможно, запустить несколько "updater", если вы делаете много обновлений)
тогда для вашего интерфейса, так как вы не хотите опрашивать сервер, я бы сделал что-то вроде 'длинный опрос'. То, что вы по существу делаете, - это опрос сервера, но сервер никогда не "отвечает", пока не произойдет изменение данные, которые вас интересуют. Как только происходит изменение, вы отвечаете на запрос. На интерфейсе у вас есть JS, повторно сделайте соединение, как только он получит последнее обновление. Это решение совместимо с кросс-браузером, если вы используете JS-фреймворк, который также является кросс-браузером (я бы предложил jQuery).
чтобы исключить опрос базы данных веб-приложений, выполните следующие действия:
сделайте первоначальный запрос длинным запросом опроса для веб-приложения, веб-приложения отправляет сообщение zmq на ваш бэкэнд (вероятно, нужно будет сделать с сокетом REQ/REP) и ждет. Он ждет, пока не получит сообщение от бэкэнда zmq с изменением состояния. Когда он получает изменение состояния, он реагирует на интерфейс с изменением. На этом этапе интерфейс отправит новый запрос длительного опроса (с этим текущим идентификатором заданий, который может быть его идентификатором), и веб-приложение снова подключится к бэкэнду и дождется другого изменения состояния. Хитрость, чтобы сделать эту работу использовать ZMQ_IDENTITY
для сокета, когда он был первоначально создан (в первом запросе). Это позволит веб-приложению повторно подключиться к тому же бэкэнд-сокету и получить новые обновления. Когда бэкэнд имеет новое обновление для отправки, он будет сигнализировать веб-приложение, которое, в свою очередь, ответит на запрос длительного опроса с его изменением состояния. Таким образом, нет polling
, нет бэкэнд-базы данных, и все события управляются от бэкэнд-работников.
Я бы установил какую-то сторожевую собаку, которая если интерфейс исчезнет (переключает страницы или закрывает браузер), бэкэнд-сокеты будут правильно закрыты. Нет необходимости для них, чтобы сидеть там indefintely блокировки, когда это измененное состояние.
опция будет использовать WebSocket. Если вы идете по этой дороге, вы можете проверить Автобан, который включает в себя клиенты и серверы для Python (Twisted), а также протокол RPC+PubSub поверх WebSocket (с libs для Python, JavaScript и Android). Использование подписки RPC+PubSub обеспечивает значительную работу и может соответствовать вашим потребностям (отправка заданий => RPC, обновления заданий => PubSub).
AutobahnPython работает на Twisted, который может дополнительно действовать как WSGI контейнер, который позволяет запускать Flask (или другую веб-структуру на основе WSGI). Вы можете запустить все на 1 порт/сервер. Для последнего есть пример на GitHub Autobahn repository.
отказ от ответственности: я оригинальный автор Autobahn и WAMP, и работать на Тавендо.
детали: Я предполагаю, что ваши работники делают CPU интенсивный и / или блокирующий материал.
во-первых, ваши рабочие чистые Python или внешние программы?
Если в последнем случае вы можете использовать экземпляры протокола скрученного процесса, которые взаимодействуют через каналы stdio (неблокирующим образом) из основного скрученного потока. Если первый, Вы можете использовать пул скрученных фоновых потоков и использовать скрученный deferToThread (см.:http://twistedmatrix.com/documents/current/core/howto/threading.html).
Autobahn бежит на главном переплетенном потоке реактора. Если ваш работник Также (см. Комментарии ранее), то вы можете напрямую вызывать методы на WebSocket/WAMP factory / экземпляры протокола. Если нет (рабочий работает в фоновом потоке), вы должны вызвать эти методы через callFromThread.
Если вы используете WAMP, главное-получить ссылку на WampServerFactory для каждого работника. Затем работник может отправить событие PubSub всем подписчикам, вызвав соответствующий заводской метод.
поскольку вы говорите о веб-приложении python, я бы рекомендовал вам изучить:
какую технологию обмена сообщениями я должен применять между веб-приложением и рабочим бэкэндом?
сельдерей - разбить работу на более мелкие задачи, которые возвращают результаты, которые должны быть показаны клиенту
какую технологию следует использовать для передачи информации в браузер?
или гнездо IO on NodeJS вид серверной части JS framework или библиотека веб-сокетов для вас python web framework
Если вы не привязаны к python слишком много, проверьте Метеор
на основе этой теме, другие способы обновления прогресса от сервера до веб-клиента в режиме реального времени могут включать запись состояния прогресса в базу данных redis или использование Oribited/ Morbid (оба основаны на Twisted) С помощью протокол топота на основе асинхронных результатов от сельдерей