我们在遗留 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 关闭钩子应该足以为我解决这个问题,希望你也觉得它有用。
正如大家所说,hazelcastInstance.shutdownAll() 是解决方案。
但是,我想在 Hazelcast 中获得一个新功能——也提供一个恶魔客户端。有许多用例需要在应用程序结束后立即关闭缓存实例。
这是一种检测 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();
}
}