4

呼び出しの結果をキャッシュし、それを要求された EJB インターフェイスにマップする Service Locator 実装を使用しているjavax.naming.Context#lookupため、最初の要求以降のすべての後続の要求 (同じ EJB に対する) は、キャッシュされたインスタンスを返します。

私の懸念は次のとおりです。

  1. 同じインスタンスが使用されるため、複数の EJB で複数の同時要求を処理するサーバー EJB プールは使用されません (基礎となるサーバー ロジックが何らかの方法で EJB プールを使用しない限り)。
  2. ステートレスおよびステートフル EJB はスレッド セーフですが、EJB クラスごとに 1 つのインスタンスのみが使用され、EJB には @PersistenceContext を介して注入された EntityManager があるため、複数のスレッドが同じ EntityManager インスタンスを使用する可能性があることを意味すると思います (永続性だけでなく) context)、これは間違いなくスレッドセーフではありません

Service Locator でキャッシングを使用しないのが最善だと思いますか、それとも EJB の動作に関する私の懸念は不当だと思いますか?

4

1 に答える 1

5

(JNDI サービスを介して) ルックアップ操作から得られるのは、スタブと呼ばれるオブジェクトであり、このオブジェクトは特別な EJB インスタンスで固定されていません。

キャッシュされると、EJB サービスを呼び出すたびに、スタブはプールから別の EJB インスタンスを選択できます (これはステートレスに適用されます)。クラスタ環境であっても、スタブ オブジェクトは異なるサーバーから EJB インスタンスを選択できます。

したがって、スタブ オブジェクトのキャッシュは問題になりません。

ステートレスについて話していることに注意してください。キャッシングはステートフル セッション Bean には意味がないと思います。

EJB ルックアップは時間のかかる操作であるため、キャッシングによりクライアントのパフォーマンスが向上します。


あなたのコメントについて:

サーブレットのような複数の同時スレッドによって使用されるコンポーネント内で EntityManager を使用していた場合、はい、並行性に注意する必要がありますが、EJB のトレッド モデルは、同じ EntityManager インスタンスを同時に使用する複数のスレッドではないことを暗示しています。であるため、EM がスレッドセーフではないという事実は問題ではありません。

私がまだ懸念しているのは、異なる EJB が (@PersistenceContext を介して) 注入された同じ EntityManager インスタンスを使用しているという事実です。

ここで説明するように、単純な風景の場合、それについて考える最良の方法だと思います:

マルチユーザー クライアント/サーバー アプリケーションで最も一般的なパターンは、entitymanager-per-request です。このモデルでは、クライアントからのリクエストがサーバー (JPA 永続レイヤーが実行されるサーバー) に送信され、新しい EntityManager が開かれ、すべてのデータベース操作がこの作業単位で実行されます。作業が完了すると (そしてクライアントへの応答が準備されると)、永続化コンテキストがフラッシュされて閉じられ、エンティティ マネージャー オブジェクトも閉じられます。

これはチェックするのがより難しくなります;)

于 2013-10-22T21:40:52.420 に答える