Решение длительной проблемы запроса в веб-приложении (асинхронный запрос)

Вот проблема

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

Проблемы:

  • Тайм-аут запроса - через некоторое время пользователь может получить тайм-аут запроса
  • Тайм-аут сессии - если никакие методы хранения сессии не используются, тайм-аут сессии, может произойти
  • Блокировка потока запроса
    • так как поток запроса не возвращается, он может заблокировать новый requrests (если достигает предела пула),
    • В некоторых серверах приложений состояние здоровья сервера могло бы инициировать принудительный перезапуск узла или приложения (из-за длительного потока запроса)
  • Если пользователь оставляет страницу:
    • транзакция не отменяется - приводящий к бесполезной обработке никого извлечет выгоду из
    • пользователь не может возвратиться для наблюдения результатов после того, как они завершатся
  • никакой признак прогресса - пользователь просто ожидает страницы для обновления

Существует несколько решений, которые я предложил, но я не уверен, что знаю, который лучше (во всех аспектах, производительности, лучшей практике, элегантности и пригодности для обслуживания), и я хотел бы знать то, что Ваше рекомендуемое решение, и если существует решение, которое я пропустил? (вероятно, да, и многие)

Плохое решение: используйте поток запроса в качестве рабочего потока, сохраните состояние прогресса на сессии, имейте проверку вызова Ajax состояние (на сессии) в другом параллельном запросе

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

Решение J2EE: используйте JMS для асинхронной задачи, это - то, для чего это является ment

решение для Spring: используйте пакет Spring

То, что Вы сделали бы / сделало в Ваших проектах? Что другие решения Вы знаете? то, которое из тех я отметил выше, является победителем по Вашему мнению?

8
задан Eran Medan 30 December 2009 в 09:32
поделиться

4 ответа

Я бы сделал комбинацию твоего так называемого "плохого решения" и "решения j2ee":

  1. Исходный поток интерфейса пользователя посылает асинхронное сообщение JMS на "бэкэнд" и возвращает его.
  2. Бэкэнд принимает асинхронный запрос и обрабатывает его.
  3. Когда в бэкэнде достигается результат (или ошибка), он возвращается на уровень контроллера.
  4. Интерфейс, все еще опрашивающий AJAX или использующий Bayeux/Cometed, получает и отображает результат.

Хитрость заключается в совпадении пары запрос/ответ. Я бы сделал это так:

  1. Создайте "AsyncManagerService" (AMS), у которого есть СЕССИЯ, Может быть, даже APPLICATION широкий диапазон, поэтому все потоки обращаются к одному и тому же экземпляру.
  2. AMS держит карту с id в качестве ключа и любым объектом в качестве значения.
  3. При создании запроса JMS-сообщения сгенерируйте уникальный, случайный ключ и поместите его в jmsCorrelationId сообщения, а также в карту, со значением NULL. Также передайте этот идентификатор в пользовательский интерфейс.
  4. Пусть поток пользовательского интерфейса опросит AMS с ранее сгенерированным идентификатором до тех пор, пока значение на карте будет NULL.
  5. Когда результат будет готов, пусть приемник JMS поместит его в карту AMS на данном идентификаторе.
  6. В следующий раз, когда поток пользовательского интерфейса будет опрашивать карту, он получит ответ и прекратит опрос.

Это чистое и хорошо абстрагированное значение из любого конкретного домена. Чисто техническое решение.

Даже если вам не нравится опрос, HTTP по своей природе является апатридом, и я думаю, что таким образом опрос происходит только через четко определенные промежутки времени.

В любом случае, я реализовал систему именно с таким паттерном, и она работает просто отлично...

.
13
ответ дан 5 December 2019 в 11:25
поделиться

Покажите пользователю сообщение о том, что "Ваш запрос принят и обновление займет час"

Вы создаете таблицу, в которой хранятся все эти транзакции и обрабатываете их пакетно на сервере.

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

Это лучшее решение, на мой взгляд.

.
1
ответ дан 5 December 2019 в 11:25
поделиться

Решение, которое я использовал раньше, включает Jetty Cometd вместо AJAX. Основное различие между Ajax и Cometd заключается в том, что Cometd может использовать больше модели pub/sub - клиент (в данном случае web-браузер) подписывается на издателя (ваше приложение) и приложение выталкивает обновления и уведомления в web-браузер, как в случае с ajax моделью постоянного опроса сервера web-браузером. Вы можете использовать решение Cometd, даже если вы не используете jetty - вы можете бросить банку с приставкой в папку lib вашего соответствующего веб-сервера, и вы должны быть готовы к работе

.
1
ответ дан 5 December 2019 в 11:25
поделиться

Как долго выполняются эти запросы?

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

Итак, если речь идет о действительно длинных запросах, возможно, лучше изменить подход к пользовательскому интерфейсу и заставить пользователя "заказать" запрос, который он (она) позже вернётся к просмотру, или даже получит уведомление по почте, когда он будет готов.

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

.
0
ответ дан 5 December 2019 в 11:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: