4

クラスター化された JEE6 環境 (Glassfish 3.1.2) では、@Singleton すべてのクラスター ノードで Bean を作成できます。このシングルトン Bean がプログラム タイマーを登録する場合@PostConstruct、メソッドはどのくらいの頻度で@Timeout実行されますか? -- そのシングルトンの 1 つだけ (ティックごと)、またはそのタイマーを登録した各 Singeton に対して 1 回 (ティックごと) に?

コードの下に、この質問がこのコードにとって何を意味するかの例を示します。

@Singleton
public class CachedService {

@Resource
private TimerService timerService;

    private static final long CACHE_TIMEOUT_DURATION_MS = 60 * 60 * 1000;

    @PostConstruct
    void initResetTimer() {
        this.timerService.createIntervalTimer(CACHE_TIMEOUT_DURATION_MS,
            CACHE_TIMEOUT_DURATION_MS,
            new TimerConfig("current user cache timeout", false));
    }

    @Timeout
    public void executeResetTimer() {
        this.clearCache();
    }
}

例: アプリケーションは、クラスター内の 3 つのノードで実行されます。シングルトンがすべてのノードでインスタンス化されると仮定すると、initResetTimer合計で 3 回 (ノードごとに 1 回) 実行されます。次に問題は、 1 時間に 1 回、すべてのノードでキャッシュがクリアされる (呼び出される) かどうかです。executeResetTimer

(シングルトンは異なる時間にインスタンス化されるため、すべてのノードでタイマーが同時に作動しないことはわかっていますが、これは問題/質問ではありません。)

4

3 に答える 3

4

まず、ここで説明するように、外部共有XAデータソースへのタイマーサービスが設定されていることを確認します。

過去にあなたの質問を掘り下げたことがありますが、メーリングリストの開発者によるGlassfishの実装は次のような説明を覚えています。

クラスタにノードA、B、Cがあるとします。ノードAで作成された永続タイマーは、ノードAによって「所有」されます(つまり、タイマーイベントはノードAに配信されます)。ノードAに障害が発生した場合、そのタイマーを別のライブノードに移行できます。

Glassfishがクラスター全体をサポートしていないため@Singletons、への呼び出しと同じ数のタイマーが発生しinitResetTimer()ます。さらに、サーバーの再起動/再デプロイごとに、キャンセルされていない古いタイマーに加えて、クラスターノードごとに新しいタイマーのインスタンスが作成される可能性があるため、プログラムで作成されたタイマーをキャンセルすることを忘れないでください:)これをすべて回避するには、宣言型@Schedule(...)アプローチを使用すると、Glassfishが作成しますタイマーはクラスター全体で1回実行され、失敗した場合は自動的に移行されます。

お役に立てれば。

アップデート:

プログラムで作成されたタイマーは、永続的または非永続的であり、クラスター化されたセットアップであるかどうかに関係なく、作成されたJVM/ノードで起動されます。大まかに要約すると、独立したタイマーインスタンスの数は、timer.createXxxTimer()

于 2012-07-13T06:56:07.337 に答える
2

EJB 3.1仕様の第18章「Timer Service」を見ました。アプリは、クラスタリングとは関係なく、仕様に従って動作する必要があります。

私の理解ではcreateIntervalTimer、クラスターで が 1 回呼び出された場合、タイマーはクラスター内のノード数に関係なく 1 回起動する必要があります。各シングルトン Bean (質問によると) は を呼び出すため、 ncreateIntervalTimer実行されます。ServletContextListener でタイマーを作成するのと似ています。

ただし、これは理論です。ターゲットとする特定のアプリ サーバーを再確認します。Glassfish では、クラスター全体のタイマーは、外部データベースを使用してタイマー プールを構成する必要があります。

于 2012-07-04T11:53:53.807 に答える
1

直接的な応答ではない場合でも、これはとにかく役立つ可能性があります。クラスター化された環境ごとに1つのインスタンスのみを構成する1つの方法は、シングルトンejbをMXbeanとして公開することです。マネージドインターフェイスを公開する必要があります。これは空の場合もあります。次に、@PostCostructマーク付きメソッドでejbをjmxサービスに登録します。最後に、jmxサービスから登録解除するために@PreDestroyフックを提供する必要があります。これは、JavaチャンピオンのAdamBienによって提案された方法です。

于 2012-07-09T09:06:13.403 に答える