2012-03-02 4 views
1

Я использую Spring MVC 3 + Tiles для webapp. У меня медленная работа, и я бы хотел, пожалуйста, подождите.Пожалуйста, подождите страницу Spring MVC + Apache Tiles

Есть два основных подхода к Пожалуйста, подождите страницы, о которых я знаю:

  1. долгоживущих запросов: визуализации и промыть «Пожалуйста, подождите» немного страницы, но не выполнить запрос пока действие не завершится, и в этот момент вы можете передать остальную часть ответа с помощью некоторого javascript для перенаправления или обновления страницы.
  2. Немедленно возвращайтесь и начинайте обработку на фоновом потоке. Клиент проверяет сервер (в javascript или через обновление страницы) и перенаправляет, когда заканчивается фоновый поток.

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

Итак, я начал внедрять (2). В моей реализации первый запрос запускает операцию в фоновом потоке, используя аннотацию Spring @Async, которая возвращает Future<Result>. Затем он возвращает пользователю страницу «Подождите», которая обновляется каждые несколько секунд.

Когда страница ожидания подождите, обновляется, контроллер должен проверить ход фонового потока. Каков наилучший способ сделать это?

  1. Если я положил объект Future в сеанс напрямую, то потоки запроса опроса могут вытащить его и проверить ход потока. Однако не означает ли это, что мои сеансы не являются сериализуемыми, поэтому мое приложение не может быть развернуто с несколькими веб-серверами (без необходимости использования липких сеансов)?
  2. Я мог бы поставить какой-то флаг состояния в сеанс, а фоновый поток обновить сеанс, когда он будет завершен. Я очень обеспокоен тем, что передача объекта HttpSession в поток без запроса приведет к отладке ошибок. Это разрешено? Может ли кто-нибудь ссылаться на любую документацию в любом случае? Он отлично работает, когда сеансы хранятся в памяти, конечно, но что делать, если сеансы хранятся в базе данных? Что делать, если у меня есть несколько веб-серверов?
  3. Я мог бы установить какой-то флаг состояния в моей базе данных, используя ключ сеанса или какой-либо другой аспект медленной операции. Кажется странным иметь данные сеанса в моей базе данных домена, а не в сеансе, но, по крайней мере, я знаю, что база данных является потокобезопасной.
  4. Есть ли еще один вариант, который я пропустил?

ответ

1

Часть вашего вопроса Spring MVC довольно проста, так как проблема не имеет ничего общего с Spring MVC. См. Возможное решение в этом ответе: https://stackoverflow.com/a/4427922/734687

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

  • Невозможно сериализовать будущее и позволить ему перейти на второй экземпляр сервера. Нить выполняется в определенном экземпляре и поэтому должна оставаться там. Таким образом, хранилище сеансов не является вариантом.
  • Как и в примере ссылки, вы можете использовать службу токенов.Обычно это HashMap, где вы можете сохранить свой объект и снова получить доступ к нему через токен (идентификатор строки). Но опять же, это работает только в одном и том же веб-приложении, когда tokenService является одноэлементным.

Решение не для того, чтобы сохранить будущее, а вместо этого состояние работы (в работе, закончилось, не удалось с результатом). Даже когда сеанс запросов и исполняемые потоки находятся на разных машинах, состояние должно быть доступно и возможность сериализации. Но как бы вы это сделали? Это можно реализовать, сохранив его в базе данных или в файловой системе (пример выше, вы можете проверить, доступен ли zip-файл) или в хранилище ключей/значений или в кеше или в общем хранилище объектов (Terracota), ...

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

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

+0

Могу ли я обобщить ваш ответ как (2) из ​​первого списка и (3) из второго списка? У меня есть одна основная проблема с наличием данных с областью действия в базе данных: база данных не автоматически связана с сеансом, поэтому мне нужно будет добавить задание на очистку, чтобы периодически проверять базу данных на данные мертвой сессии и удалять ее. Как вы думаете (2) из ​​второго списка жизнеспособны? У вас есть доказательства относительно того, безопасно или нет доступ к объектам сеанса из потоков без запроса? Это позволит избежать несоответствия области видимости. – Rich

+0

Я бы придерживался 2-3, а не 2-2. Я бы не обновил сеанс. Я не думаю, что это возможно вообще. Скажем, сеанс 1 активен на сервере 1, и фон-поток на сервере 2 также хотел бы изменить сеанс. Это невозможно. – ChrLipp

+0

Обычно архитектура выглядит так: выполнять действия в режиме онлайн, когда продолжительность составляет менее 3 минут. Если у вас есть длительное действие, сохраните запрос в базе данных и позвольте ему обработать пакетный планировщик. Планировщик может работать на дополнительном сервере. Нет необходимости хранить что-либо в сеансе. – ChrLipp