0

サーバーの起動時またはアプリケーションの展開時にキャッシュを初期化する際の問題に直面しています。キャッシュの初期化には、

  1. データベースにクエリを実行してアイテムのリストを取得する
  2. 各アイテムの rmi 呼び出しを行う
  3. JMS キュー/トピックのデータをリッスンする
  4. キャッシュの構築

この初期化プロセスはスタートアップ コードにあります。展開に多くの時間がかかっているか、サーバーの起動時間が増加しているため、これらすべてに多くの時間がかかっています。

そこで私が提案したのは、起動時にスレッドを作成し、その中で初期化コードを実行することです。それを示すためにサンプルアプリケーションを書きました。

これには、フィルターである ServletContextListener が含まれます。リスナーでは、HeavyProcess が実行される新しいスレッドを作成しています。終了すると、フィルターがリッスンするイベントが発生します。イベントを受信すると、フィルターは着信 http 要求を許可します。それまでは、フィルタはすべてのクライアントを、アプリケーションが初期化中であるというメッセージを表示するデフォルト ページにリダイレクトします。

私はこのアプローチを提示しましたが、懸念事項はほとんどありませんでした。

  1. スレッドの処理が難しいため、理想的にはスレッドを作成しないでください。

私の質問は、Web アプリケーションでこのようなスレッドを作成できない理由です。

これが良くない場合、最善のアプローチは何ですか?

4

2 に答える 2

0

一般に、Java EE 環境でアンマネージ スレッドを作成することはお勧めできません。アンマネージド スレッド内では、コンテナー管理のトランザクション、ユーザー コンテキスト、およびその他の多くの Java EE 概念が失われます。さらに、スレッドの処理が適切でない場合、管理されていないスレッドがシャットダウン時にコンテナをブロックする可能性があります。

どの Java EE バージョンを使用していますか? おそらく、 Servlet 3.0 の非同期機能を使用できますか?

または、起動時に重い処理を行うために非同期 EJB を呼び出します ( @PostConstruct )。呼び出しは、ジョブが完了するとフラグを設定します。

于 2013-08-29T14:55:53.780 に答える
0

マネージド スレッドを使用できる場合は、アンマネージド スレッドは避けてください。コンテナはアンマネージ スレッドを制御できず、アンマネージ スレッドを適切に終了しないと、アンマネージ スレッドが再デプロイされても存続します。したがって、管理されていないスレッドを登録し、これらを何らかの方法で終了する必要があります (競合状態を慎重に処理する必要があるため、これも簡単ではありません)。


したがって、1 つの解決策は@Startup、次のようなものを使用することです。

@Schedule(second = "*/45", minute = "*", hour = "*")
protected void asyncInit(final Timer timer) {
    timer.cancel();

    // Do init here

    // Set flag that init has been completed
}

ここでこの方法について学びました: Java EE アプリケーションのデプロイ後にタスクを実行する

したがって、これにより非同期マネージド スレッドが提供され、展開が遅延することはありません@PostConstruct。に注意してくださいtimer.cancel()


実際の問題を見ると、「ウォームスタート」をサポートするキャッシュを使用することをお勧めします。

たとえば、Infinispanはキャッシュ ストアをサポートしているため、キャッシュ コンテンツは再起動後も存続します。クラスターがある場合は、分散または複製されたキャッシュ モードもあります。

JBoss 7 には Infinispan (同じ JVM に統合されたサービス) が組み込まれていますが、独立して運用することもできます。

もう 1 つの候補はRedisです(永続性を備えた他のキー/値ストアも同様です)。

于 2013-08-29T18:25:09.583 に答える