3

我们在遗留 Java 集群应用程序中使用 Hazelcast 2.6.2。当应用程序停止时,JVM 不再终止。这似乎是由于 Hazelcast 线程没有被标记为守护进程。我没有找到通过 Hazelcast API 标记它们守护进程的方法。

是否有推荐的解决方案来防止 Hazelcast 阻止 JVM 终止?

问候

4

4 回答 4

2

查看Hazelcast Javadocs,我看到有一种shutdownAll();方法。引用 javadocs:

关闭此 JVM 上所有正在运行的 Hazelcast 实例,包括正在运行的默认实例。它不会关闭集群的所有成员,而只会关闭在此 JVM 上运行的成员。

如果您不关闭它,我怀疑那里有非守护线程没有被终止,这将阻止 JVM 关闭。

于 2013-09-09T16:06:10.000 回答
1

在 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 关闭钩子应该足以为我解决这个问题,希望你也觉得它有用。

于 2013-10-31T15:27:00.597 回答
0

正如大家所说,hazelcastInstance.shutdownAll() 是解决方案。

但是,我想在 Hazelcast 中获得一个新功能——也提供一个恶魔客户端。有许多用例需要在应用程序结束后立即关闭缓存实例。

于 2015-03-06T02:33:26.090 回答
0

这是一种检测 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();
    }
}
于 2013-10-31T16:39:33.933 回答