従来の Java クラスター化アプリケーションで Hazelcast 2.6.2 を使用しています。アプリケーションが停止すると、JVM はそれ以上終了しません。Hazelcast スレッドがデーモンにフラグを立てていないことが原因のようです。Hazelcast API を介してデーモンにフラグを立てる方法が見つかりませんでした。
Hazelcast が JVM の終了を妨げないようにするための推奨される解決策はありますか?
よろしく
従来の Java クラスター化アプリケーションで Hazelcast 2.6.2 を使用しています。アプリケーションが停止すると、JVM はそれ以上終了しません。Hazelcast スレッドがデーモンにフラグを立てていないことが原因のようです。Hazelcast API を介してデーモンにフラグを立てる方法が見つかりませんでした。
Hazelcast が JVM の終了を妨げないようにするための推奨される解決策はありますか?
よろしく
Hazelcast Javadocsを見ると、shutdownAll();
メソッドがあることがわかります。javadocs を引用するには:
この JVM で実行中のすべての Hazelcast インスタンス (実行中の場合はデフォルトのものを含む) をシャットダウンします。クラスターのすべてのメンバーをシャットダウンするのではなく、この JVM で実行されているメンバーのみをシャットダウンします。
シャットダウンしていない場合は、終了していないデーモン以外のスレッドがあり、JVMが閉じないようになっていると思われます。
Tomcat では、server.xml を介してライフサイクル リスナーを追加しました。
<Listener className="com.mycompany.StartupHandler" DEBUG="false"/>
私の StartupHandler.class は $TOMCAT_HOME/lib/ の jar に入れられ、Tomcat のシャットダウンが検出されたときに Hazelcast のシャットダウンをトリガーする次のスニペットが含まれています。
public void lifecycleEvent(LifecycleEvent lifecycleEvent) {
String eventType = lifecycleEvent.getType();
if (eventType.equals(Lifecycle.BEFORE_STOP_EVENT)) {
com.hazelcast.core.Hazelcast.shutdownAll();
}
}
他の Web サーバーには、Hazelcast.shutdownAll() を自動的に呼び出すことができる同様のシャットダウン フックが必要です。
同じトピックに関する私の元の Hazelcast スレッドについては、https://github.com/hazelcast/hazelcast/issues/718を参照してください。ここで Hazelcast.shutdownAll() を呼び出すヒントをありがとう。このアイデアと Tomcat のシャットダウン フックを組み合わせると、この問題を解決するのに十分なはずです。
JVM のシャットダウンを検出する Tomcat に依存しない方法を次に示します。非デーモン スレッドを使用してデーモン スレッドをポーリングし、JVM がいつシャットダウンするかを検出します (JVM はデーモン スレッドを自動的にシャットダウンします)。コードで静的な IS_SHUTDOWN フラグをポーリングするか、ここで Hazelcast.shutdownAll() への呼び出しをインライン化します。開始前に Hazelcast をシャットダウンしようとすると、ログに例外がスローされるため、競合状態に注意してください。例外は何も壊しませんが、見栄えが悪いです。
/**
* Non-Daemon thread monitors a sacrificial, low-priority, daemon thread
* to detect when JVM is shutting down, so shutdown hooks can be invoked.
* @author justin.cranford
*/
public class ThreadUtil {
public static boolean IS_SHUTDOWN = false; // threads can poll this flag, or inline below where flag is set
private static final Thread DAEMON_THREAD = new Thread() {
public void run() {
while (true) {
try {
Thread.sleep(Long.MAX_VALUE); // sleep forever
} catch(Exception e) {}
}
}
};
private static final Thread NONDAEMON_THREAD = new Thread() {
public void run() {
while (true) {
if (!DAEMON_THREAD.isAlive()) { // poll forever, until daemon thread dies
ThreadUtil.IS_SHUTDOWN = true;
return;
}
try {
Thread.sleep(1000); // poll every 1000msec = 1sec
} catch(Exception e) {}
}
}
};
static {
DAEMON_THREAD.setName("ShutdownMonitorNonDaemonThread");
DAEMON_THREAD.setPriority(Thread.MIN_PRIORITY);
DAEMON_THREAD.setDaemon(true);
DAEMON_THREAD.start();
try {
Thread.sleep(3000); // wait 3000msec = 3sec before monitoring
} catch(Exception e) {}
NONDAEMON_THREAD.setName("ShutdownMonitorDaemonThread");
NONDAEMON_THREAD.setPriority(Thread.MIN_PRIORITY);
NONDAEMON_THREAD.setDaemon(false);
NONDAEMON_THREAD.start();
}
}