如何在 spring 启动时禁用 Hazelcast 的默认关闭钩子
How to disable default shutdown hook of Hazelcast in spring boot
我正在使用 Hazelcast 开发网络套接字应用程序来共享在线用户的状态。一切工作正常,除了一件事,当其中一个应用程序实例关闭或重新启动时,连接到该实例的所有用户都断开连接并且 MessagingHandler
的 afterConnectionClosed
扩展 BinaryWebSocketHandler
。在 afterConnectionClosed
中,连接到当前节点的用户的状态将被更新,这些状态在 Hazelcast 中。因此,当它尝试从 Hazelcast 中删除状态时,会出现以下错误:
com.hazelcast.core.HazelcastInstanceNotActiveException: State: SHUT_DOWN Operation: class com.hazelcast.map.impl.operation.RemoveOperation
at com.hazelcast.spi.impl.operationservice.impl.Invocation.engineActive(Invocation.java:490)
at com.hazelcast.spi.impl.operationservice.impl.Invocation.doInvoke(Invocation.java:523)
at com.hazelcast.spi.impl.operationservice.impl.Invocation.invoke0(Invocation.java:513)
at com.hazelcast.spi.impl.operationservice.impl.Invocation.invoke(Invocation.java:207)
at com.hazelcast.spi.impl.operationservice.impl.InvocationBuilderImpl.invoke(InvocationBuilderImpl.java:60)
at com.hazelcast.map.impl.proxy.MapProxySupport.invokeOperation(MapProxySupport.java:423)
at com.hazelcast.map.impl.proxy.MapProxySupport.removeInternal(MapProxySupport.java:563)
at com.hazelcast.map.impl.proxy.MapProxyImpl.remove(MapProxyImpl.java:207)
at com.nisheeth.spring.MessageHandler.afterConnectionClosed(MessageHandler.java:57)
at org.springframework.web.socket.handler.WebSocketHandlerDecorator.afterConnectionClosed(WebSocketHandlerDecorator.java:85)
at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.afterConnectionClosed(LoggingWebSocketHandlerDecorator.java:72)
at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.afterConnectionClosed(ExceptionWebSocketHandlerDecorator.java:78)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.onClose(StandardWebSocketHandlerAdapter.java:141)
at org.apache.tomcat.websocket.WsSession.fireEndpointOnClose(WsSession.java:535)
at org.apache.tomcat.websocket.WsSession.doClose(WsSession.java:481)
at org.apache.tomcat.websocket.WsSession.close(WsSession.java:445)
at org.apache.tomcat.websocket.WsWebSocketContainer.destroy(WsWebSocketContainer.java:960)
at org.apache.tomcat.websocket.server.WsContextListener.contextDestroyed(WsContextListener.java:48)
at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4792)
at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5429)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:226)
at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1435)
at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1424)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
at ------ submitted from ------.(Unknown Source)
at com.hazelcast.spi.impl.operationservice.impl.InvocationFuture.resolve(InvocationFuture.java:127)
at com.hazelcast.spi.impl.operationservice.impl.InvocationFuture.resolveAndThrowIfException(InvocationFuture.java:79)
at com.hazelcast.spi.impl.AbstractInvocationFuture.get(AbstractInvocationFuture.java:147)
at com.hazelcast.map.impl.proxy.MapProxySupport.invokeOperation(MapProxySupport.java:424)
at com.hazelcast.map.impl.proxy.MapProxySupport.removeInternal(MapProxySupport.java:563)
at com.hazelcast.map.impl.proxy.MapProxyImpl.remove(MapProxyImpl.java:207)
at com.nisheeth.spring.MessageHandler.afterConnectionClosed(MessageHandler.java:57)
at org.springframework.web.socket.handler.WebSocketHandlerDecorator.afterConnectionClosed(WebSocketHandlerDecorator.java:85)
at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.afterConnectionClosed(LoggingWebSocketHandlerDecorator.java:72)
at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.afterConnectionClosed(ExceptionWebSocketHandlerDecorator.java:78)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.onClose(StandardWebSocketHandlerAdapter.java:141)
at org.apache.tomcat.websocket.WsSession.fireEndpointOnClose(WsSession.java:535)
at org.apache.tomcat.websocket.WsSession.doClose(WsSession.java:481)
at org.apache.tomcat.websocket.WsSession.close(WsSession.java:445)
at org.apache.tomcat.websocket.WsWebSocketContainer.destroy(WsWebSocketContainer.java:960)
at org.apache.tomcat.websocket.server.WsContextListener.contextDestroyed(WsContextListener.java:48)
at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4792)
at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5429)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:226)
at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1435)
at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1424)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
我正在使用以下属性禁用默认关机:
config.setProperty(GroupProperty.SHUTDOWNHOOK_ENABLED.getName(), "false");
config.setProperty(GroupProperty.SHUTDOWNHOOK_POLICY.getName(), "GRACEFUL");
但在用户断开连接之前它仍然处于关闭状态。有没有办法以在应用程序结束时关闭 hazelcast 的方式配置 hazelcast?
@nisheeth-shah,这更像是一个 Spring 相关的问题,因为它 Spring 决定了 bean 的关闭顺序。
你可以做什么,你可以用 @DependsOn
注释来注释你的 MessageHandler
bean 并给出 HazelcastInstance
bean 的名称,就像这样 @DependsOn("hazelcastInstance")
。请参阅此 link 以获取解释。基本上,Spring 将在创建 MessageHandler
之前启动 HazelcastInstance
,并且不会在 MessageHandler
bean 销毁之前关闭 HazelcastInstance
。
此外,不要禁用 Hazelcast 关闭钩子。
我一直在尝试不同的方法来处理正常关闭 spring websocket 连接,这也修改了在线用户的 hazelcast 地图,但是 none 有效。我终于使用了 SmartLifecycle
接口。 class 的文档可以在 here.
中找到
这是我用于正确关机的代码。是的,它在 Hazelcast 关闭之前被调用:
@Component
public class AppLifecycle implements SmartLifecycle {
private Logger log = LoggerFactory.getLogger(AppLifecycle.class);
@Autowired
private SampleService sampleService;
@Override
public boolean isAutoStartup() {
log.debug("=========================auto startup=========================");
return true;
}
@Override
public void stop(Runnable runnable) {
sampleService.getSessionMap().forEach((key, session) -> {
try {
session.close(CloseStatus.SERVICE_RESTARTED);
log.debug("disconnecting : {}", key);
} catch (IOException e) {
log.error(e.getMessage(), e);
}
});
log.debug("=========================stop runnable=========================");
new Thread(runnable).start();
}
@Override
public void start() {
log.debug("=========================start=========================");
}
@Override
public void stop() {
log.debug("=========================stop=========================");
}
@Override
public boolean isRunning() {
return true;
}
@Override
public int getPhase() {
return Integer.MAX_VALUE;
}
}
您可以在 @PreDestroy
中使用 hazelcastInstance.shutdown()
即
@PreDestroy
public void shutDownHazelcast(){
hazelcastInstance.shutdown()
}
这将正常关闭 hazelcast 实例
我正在使用 Hazelcast 开发网络套接字应用程序来共享在线用户的状态。一切工作正常,除了一件事,当其中一个应用程序实例关闭或重新启动时,连接到该实例的所有用户都断开连接并且 MessagingHandler
的 afterConnectionClosed
扩展 BinaryWebSocketHandler
。在 afterConnectionClosed
中,连接到当前节点的用户的状态将被更新,这些状态在 Hazelcast 中。因此,当它尝试从 Hazelcast 中删除状态时,会出现以下错误:
com.hazelcast.core.HazelcastInstanceNotActiveException: State: SHUT_DOWN Operation: class com.hazelcast.map.impl.operation.RemoveOperation
at com.hazelcast.spi.impl.operationservice.impl.Invocation.engineActive(Invocation.java:490)
at com.hazelcast.spi.impl.operationservice.impl.Invocation.doInvoke(Invocation.java:523)
at com.hazelcast.spi.impl.operationservice.impl.Invocation.invoke0(Invocation.java:513)
at com.hazelcast.spi.impl.operationservice.impl.Invocation.invoke(Invocation.java:207)
at com.hazelcast.spi.impl.operationservice.impl.InvocationBuilderImpl.invoke(InvocationBuilderImpl.java:60)
at com.hazelcast.map.impl.proxy.MapProxySupport.invokeOperation(MapProxySupport.java:423)
at com.hazelcast.map.impl.proxy.MapProxySupport.removeInternal(MapProxySupport.java:563)
at com.hazelcast.map.impl.proxy.MapProxyImpl.remove(MapProxyImpl.java:207)
at com.nisheeth.spring.MessageHandler.afterConnectionClosed(MessageHandler.java:57)
at org.springframework.web.socket.handler.WebSocketHandlerDecorator.afterConnectionClosed(WebSocketHandlerDecorator.java:85)
at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.afterConnectionClosed(LoggingWebSocketHandlerDecorator.java:72)
at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.afterConnectionClosed(ExceptionWebSocketHandlerDecorator.java:78)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.onClose(StandardWebSocketHandlerAdapter.java:141)
at org.apache.tomcat.websocket.WsSession.fireEndpointOnClose(WsSession.java:535)
at org.apache.tomcat.websocket.WsSession.doClose(WsSession.java:481)
at org.apache.tomcat.websocket.WsSession.close(WsSession.java:445)
at org.apache.tomcat.websocket.WsWebSocketContainer.destroy(WsWebSocketContainer.java:960)
at org.apache.tomcat.websocket.server.WsContextListener.contextDestroyed(WsContextListener.java:48)
at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4792)
at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5429)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:226)
at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1435)
at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1424)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
at ------ submitted from ------.(Unknown Source)
at com.hazelcast.spi.impl.operationservice.impl.InvocationFuture.resolve(InvocationFuture.java:127)
at com.hazelcast.spi.impl.operationservice.impl.InvocationFuture.resolveAndThrowIfException(InvocationFuture.java:79)
at com.hazelcast.spi.impl.AbstractInvocationFuture.get(AbstractInvocationFuture.java:147)
at com.hazelcast.map.impl.proxy.MapProxySupport.invokeOperation(MapProxySupport.java:424)
at com.hazelcast.map.impl.proxy.MapProxySupport.removeInternal(MapProxySupport.java:563)
at com.hazelcast.map.impl.proxy.MapProxyImpl.remove(MapProxyImpl.java:207)
at com.nisheeth.spring.MessageHandler.afterConnectionClosed(MessageHandler.java:57)
at org.springframework.web.socket.handler.WebSocketHandlerDecorator.afterConnectionClosed(WebSocketHandlerDecorator.java:85)
at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.afterConnectionClosed(LoggingWebSocketHandlerDecorator.java:72)
at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.afterConnectionClosed(ExceptionWebSocketHandlerDecorator.java:78)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.onClose(StandardWebSocketHandlerAdapter.java:141)
at org.apache.tomcat.websocket.WsSession.fireEndpointOnClose(WsSession.java:535)
at org.apache.tomcat.websocket.WsSession.doClose(WsSession.java:481)
at org.apache.tomcat.websocket.WsSession.close(WsSession.java:445)
at org.apache.tomcat.websocket.WsWebSocketContainer.destroy(WsWebSocketContainer.java:960)
at org.apache.tomcat.websocket.server.WsContextListener.contextDestroyed(WsContextListener.java:48)
at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4792)
at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5429)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:226)
at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1435)
at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1424)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
我正在使用以下属性禁用默认关机:
config.setProperty(GroupProperty.SHUTDOWNHOOK_ENABLED.getName(), "false");
config.setProperty(GroupProperty.SHUTDOWNHOOK_POLICY.getName(), "GRACEFUL");
但在用户断开连接之前它仍然处于关闭状态。有没有办法以在应用程序结束时关闭 hazelcast 的方式配置 hazelcast?
@nisheeth-shah,这更像是一个 Spring 相关的问题,因为它 Spring 决定了 bean 的关闭顺序。
你可以做什么,你可以用 @DependsOn
注释来注释你的 MessageHandler
bean 并给出 HazelcastInstance
bean 的名称,就像这样 @DependsOn("hazelcastInstance")
。请参阅此 link 以获取解释。基本上,Spring 将在创建 MessageHandler
之前启动 HazelcastInstance
,并且不会在 MessageHandler
bean 销毁之前关闭 HazelcastInstance
。
此外,不要禁用 Hazelcast 关闭钩子。
我一直在尝试不同的方法来处理正常关闭 spring websocket 连接,这也修改了在线用户的 hazelcast 地图,但是 none 有效。我终于使用了 SmartLifecycle
接口。 class 的文档可以在 here.
这是我用于正确关机的代码。是的,它在 Hazelcast 关闭之前被调用:
@Component
public class AppLifecycle implements SmartLifecycle {
private Logger log = LoggerFactory.getLogger(AppLifecycle.class);
@Autowired
private SampleService sampleService;
@Override
public boolean isAutoStartup() {
log.debug("=========================auto startup=========================");
return true;
}
@Override
public void stop(Runnable runnable) {
sampleService.getSessionMap().forEach((key, session) -> {
try {
session.close(CloseStatus.SERVICE_RESTARTED);
log.debug("disconnecting : {}", key);
} catch (IOException e) {
log.error(e.getMessage(), e);
}
});
log.debug("=========================stop runnable=========================");
new Thread(runnable).start();
}
@Override
public void start() {
log.debug("=========================start=========================");
}
@Override
public void stop() {
log.debug("=========================stop=========================");
}
@Override
public boolean isRunning() {
return true;
}
@Override
public int getPhase() {
return Integer.MAX_VALUE;
}
}
您可以在 @PreDestroy
中使用 hazelcastInstance.shutdown()
即
@PreDestroy
public void shutDownHazelcast(){
hazelcastInstance.shutdown()
}
这将正常关闭 hazelcast 实例