在多线程Web应用程序中访问请求范围的bean [英] Accessing request scoped beans in a multi-threaded web application

查看:117
本文介绍了在多线程Web应用程序中访问请求范围的bean的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

场景:
我们有一个在Websphere中运行的Spring托管Web应用程序。 (Spring 3.0.x,WAS 7)
webapp通过Spring的 WorkManagerTaskExecutor (配置线程池大小为10)来利用Websphere的工作管理器来执行计算密集型数据库读操作。所以基本上,一个请求来生成,比方说,生成10个不同的文档。要生成文档,只需要db读取来收集/处理数据。因此,我们基本上产生10个线程来处理10个文档,最后收集10个工作者返回的10个文档并合并它们并向客户端写回一个大响应。我们确定的是,当10个线程正在收集/处理数据时,会产生大量类似的数据库调用。因此,我们想出的是围绕最常执行的db方法创建一个Aspect来缓存响应。方面配置为单例,方面使用的缓存自动连接到方面,范围设置为请求范围,以便每个请求都有自己的缓存。

Scenario: We have a Spring managed web application that runs inside Websphere. (Spring 3.0.x, WAS 7) The webapp leverages Websphere's work manager via Spring's WorkManagerTaskExecutor (configured with a thread pool size of 10) to execute computational intensive db read operations. So basically, a request comes in to generate, lets say, 10 different documents. To generate the documents only db reads are needed to gather/process the data. So we basically spawn 10 threads to process the 10 documents and at the end gather the 10 documents returned from the 10 workers and merge them and write back one big response to the client. What we identified is that while the 10 threads are gathering/processing the data there are bunch of similar db calls made. So what we came up with is to create an Aspect around the most-executed db methods to cache the response. The aspect is configured as a singleton, and the cache the aspect uses is autowired into the aspect with a scope set to request-scope so that each request has its own cache.

问题:
现在这个方法的问题是,当线程正在进行数据库调用而Aspect是interjects时,我们得到 java.lang.IllegalStateException:找不到线程绑定请求例外。我理解的是完全有效的,因为线程正在请求上下文之外执行。

Problem: Now the problem with this approach is that when the threads are doing their db calls and the Aspect is interjects we are getting java.lang.IllegalStateException: No thread-bound request found exception. Which I understand is totally valid as the threads are being executed outside the request context.

有没有办法绕过这个问题?是否可以将带有请求范围缓存的方面应用于这些线程调用的方法?

Is there a way to circum-navigate this issue? Is it possible to apply the aspect with a request scoped cache to the methods invoked by these threads?

推荐答案

我不认为你可以直接这样做。即使你可以,也会有点难看。但是,您可以生成唯一的请求标识符(甚至 - 使用会话ID,但要小心多个选项卡),并将其传递给每个处理线程。然后,方面可以使用该id作为缓存的密钥。缓存本身也将是单例,但是会有 Map< String,X> ,其中 String 是ID和X是你的缓存结果。

I don't think you can do this directly. Even if you could, it would be a bit ugly. However, you can generate a unique request identifier (or even - use the session id, but careful with multiple tabs), and pass that to each processing thread. Then the aspect can use that id as the key to the cache. The cache itself will also be singleton, but there will be Map<String, X>, where String is the ID and X is your cached result.

为了使事情更容易处理,你可以拥有 @Async 方法(而不是而不是手动生成线程),并且每个 @Async 方法都可以将缓存ID作为其第一个参数传递。

To make things easier to handle, you can have @Async methods (rather than manually spawning threads), and each @Async method can have the cache id passed as its first parameter.

(当然,您的异步方法应该返回 Future< Result> ,以便您可以在请求线程中收集它们的结果)

(Of course, your asynchronous methods should return Future<Result> so that you can collect their results in the request thread)

这篇关于在多线程Web应用程序中访问请求范围的bean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆