Доступ к bean-объектам в области запросов в многопоточном веб-приложении - PullRequest
8 голосов
/ 03 октября 2011

Сценарий: у нас есть веб-приложение, управляемое Spring, которое работает внутри Websphere.(Spring 3.0.x, WAS 7) Веб-приложение использует диспетчер работы Websphere с помощью Spring * WorkManagerTaskExecutor (сконфигурирован с размером пула потоков 10) для выполнения операций чтения базы данных с интенсивными вычислениями.Таким образом, в основном, приходит запрос на генерацию, скажем, 10 различных документов.Для генерации документов требуется только чтение базы данных для сбора / обработки данных.Таким образом, мы в основном создаем 10 потоков для обработки 10 документов и в конце собираем 10 документов, возвращенных 10 рабочими, объединяем их и записываем один большой ответ клиенту.Мы определили, что в то время как 10 потоков собирают / обрабатывают данные, выполняется множество похожих вызовов в БД.Итак, мы пришли к тому, чтобы создать Аспект вокруг наиболее исполняемых методов БД для кеширования ответа.Аспект настроен как одноэлементный, и кэш, который использует аспект, автоматически подключается к аспекту с областью действия, установленной на область действия запроса, так что каждый запрос имеет свой собственный кэш.в том, что когда потоки выполняют свои вызовы БД и Aspect is interjects, мы получаем исключение java.lang.IllegalStateException: No thread-bound request found.Что, как я понимаю, полностью допустимо, поскольку потоки выполняются вне контекста запроса.

Есть ли способ обойти эту проблему?Можно ли применить аспект с кэшем области запроса к методам, вызываемым этими потоками?

1 Ответ

5 голосов
/ 03 октября 2011

Я не думаю, что вы можете сделать это напрямую.Даже если бы ты мог, это было бы немного некрасиво.Однако вы можете сгенерировать уникальный идентификатор запроса (или даже использовать идентификатор сеанса, но осторожно с несколькими вкладками) и передать его каждому потоку обработки.Тогда аспект может использовать этот идентификатор в качестве ключа к кешу.Сам кеш также будет одноэлементным, но будет Map<String, X>, где String - это идентификатор, а X - ваш кешированный результат.

Чтобы упростить обработку, вы можете использовать @Async методы(а не порождения потоков вручную), и каждый метод @Async может иметь идентификатор кэша, переданный в качестве первого параметра.

(Конечно, ваши асинхронные методы должны возвращать Future<Result>, чтобы вы могли собирать их результатыв ветке запроса)

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