2011-10-03 13 views
8

シナリオ: Websphere内で実行されるSpring管理Webアプリケーションがあります。 (Spring 3.0.x、WAS 7) webappは、SpringのWorkManagerTaskExecutor(スレッドプールサイズが10に設定されている)を介してWebsphereのワークマネージャを利用して、計算集約型のdb読み取り操作を実行します。つまり、基本的には、10種類の異なる文書を生成する要求があります。文書を生成するためには、データを収集/処理するためには、db読み取りが必要です。したがって、基本的に10個のスレッドを生成して10個の文書を処理し、最後に10個の文書から10個の文書を集め、それらをマージして1つの大きな応答をクライアントに書き戻します。私たちが確認したことは、10個のスレッドがデータを収集/処理している間に、同様のdbコールが多数生成されていることです。だから私たちが思いついたのは、最も実行されたdbメソッドの回りにレスポンスをキャッシュするためのAspectを作成することです。アスペクトはシングルトンとして構成され、アスペクトが使用するキャッシュはアスペクトに自動スコープされ、スコープはリクエストスコープに設定され、各リクエストには独自のキャッシュがあります。マルチスレッドWebアプリケーションで要求スコープBeanにアクセス

問題: このアプローチの問題点は、スレッドがdb呼び出しを実行していて、アスペクトが挿入されているときに、java.lang.IllegalStateException: No thread-bound request found例外が発生することです。スレッドが要求コンテキストの外で実行されているので、私は理解しています。

この問題を回避する方法はありますか?これらのスレッドによって呼び出されるメソッドにリクエストスコープのキャッシュを持つアスペクトを適用することは可能ですか?

答えて

5

私はあなたがこれを直接行うことはできないと思います。たとえできても、ちょっと醜いでしょう。しかし、一意の要求識別子を生成することもできます(またはセッションIDを使用することもできますが、複数のタブに注意してください)。そして、それを各処理スレッドに渡します。アスペクトは、そのIDをキャッシュのキーとして使用できます。キャッシュ自体もシングルトンになりますが、StringがIDであり、Xがキャッシュされた結果である場合、Map<String, X>が存在します。

処理を容易にするために、@Asyncメソッドを使用できます(スレッドを手動で生成するのではなく)。各@Asyncメソッドは、最初のパラメータとして渡されるキャッシュIDを持つことができます。

私はアプローチについて考え

+0

(もちろん、あなたの非同期メソッドを使用すると、要求スレッドでの結果を収集することができるようにFuture<Result>を返す必要があります)、私は見つける一つの欠点は、それが通過するために私を強制することです一意の要求識別子をキャッシュしたいすべてのメソッド呼び出しの下流(スレッド実行中)。また、しばらくするとキャッシュがかなり大きくならないでしょうか?その後、私はそれを定期的に管理しなければなりません。多分私はここで何かを逃しているでしょう。 – r4j1v

+0

おそらく私は自分の一意の要求識別子を格納し、それを自分自身で渡すことなくそのアスペクトで取り出すために使用できる「スレッド実行コンテキスト」がありますか? – r4j1v

+5

私はこの問題を回避することができました。私は 'WorkManagerTaskExecutor'の代わりに' SimpleAsyncTaskExecutor'を使い始めました。利点は、 'SimpleAsyncTaskExecutor'は決してスレッドを再利用しないことです。それはソリューションの半分に過ぎません。解決のもう半分は、 'RequestContextListener'の代わりに' RequestContextFilter'を使用することです。 'RequestContextFilter'は、基本的に子スレッドが親コンテキストを継承できるようにする' setThreadContextInheritable() 'メソッドを持っています。 – r4j1v

関連する問題