order
This paper focuses on the graceful shutdown enabled of artemis
gracefulShutdownEnabled
activemq-artemis-2.11.0/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImpl.java
public class ConfigurationImpl implements Configuration, Serializable { //...... private boolean gracefulShutdownEnabled = ActiveMQDefaultConfiguration.isDefaultGracefulShutdownEnabled(); private long gracefulShutdownTimeout = ActiveMQDefaultConfiguration.getDefaultGracefulShutdownTimeout(); //...... @Override public boolean isGracefulShutdownEnabled() { return gracefulShutdownEnabled; } @Override public ConfigurationImpl setGracefulShutdownEnabled(final boolean enabled) { gracefulShutdownEnabled = enabled; return this; } @Override public long getGracefulShutdownTimeout() { return gracefulShutdownTimeout; } @Override public ConfigurationImpl setGracefulShutdownTimeout(final long timeout) { gracefulShutdownTimeout = timeout; return this; } //...... }
- ConfigurationImpl defines two properties about gracefulShutdown, which are gracefulShutdown enabled (default is true) and gracefulShutdown timeout (default is - 1)
ActiveMQServerImpl
activemq-artemis-2.11.0/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java
public class ActiveMQServerImpl implements ActiveMQServer { //...... public final void stop(boolean failoverOnServerShutdown, boolean isExit) throws Exception { stop(failoverOnServerShutdown, false, false, isExit); } public void stop(boolean failoverOnServerShutdown, final boolean criticalIOError, boolean restarting) { this.stop(failoverOnServerShutdown, criticalIOError, restarting, false); } void stop(boolean failoverOnServerShutdown, final boolean criticalIOError, boolean restarting, boolean isShutdown) { logger.debug("Stopping server"); synchronized (this) { if (state == SERVER_STATE.STOPPED || state == SERVER_STATE.STOPPING) { return; } state = SERVER_STATE.STOPPING; if (fileStoreMonitor != null) { fileStoreMonitor.stop(); fileStoreMonitor = null; } if (failoverOnServerShutdown) { activation.sendLiveIsStopping(); } stopComponent(connectorsService); // we stop the groupingHandler before we stop the cluster manager so binding mappings // aren't removed in case of failover if (groupingHandler != null) { managementService.removeNotificationListener(groupingHandler); stopComponent(groupingHandler); } stopComponent(federationManager); stopComponent(clusterManager); if (remotingService != null) { remotingService.pauseAcceptors(); } // allows for graceful shutdown if (remotingService != null && configuration.isGracefulShutdownEnabled()) { long timeout = configuration.getGracefulShutdownTimeout(); try { if (timeout == -1) { remotingService.getConnectionCountLatch().await(); } else { remotingService.getConnectionCountLatch().await(timeout); } } catch (InterruptedException e) { ActiveMQServerLogger.LOGGER.interruptWhilstStoppingComponent(remotingService.getClass().getName()); } } freezeConnections(); } //...... } static void stopComponent(ActiveMQComponent component) { try { if (component != null) { component.stop(); } } catch (Throwable t) { ActiveMQServerLogger.LOGGER.errorStoppingComponent(t, component.getClass().getName()); } } //...... }
- ActiveMQServerImpl will read configuration. Getgracefullshutdown timeout() when remotingService is not null and configuration. Isgracefullshutdown enabled() is true; if timeout is - 1, remotingService.getConnectionCountLatch().await() will be executed; otherwise, remotingService.getConnectionCountLatch().await(timeout) will be executed
connectionCountLatch
activemq-artemis-2.11.0/artemis-server/src/main/java/org/apache/activemq/artemis/core/remoting/server/impl/RemotingServiceImpl.java
public class RemotingServiceImpl implements RemotingService, ServerConnectionLifeCycleListener { //...... private final ReusableLatch connectionCountLatch = new ReusableLatch(0); //...... public synchronized ReusableLatch getConnectionCountLatch() { return connectionCountLatch; } public void connectionCreated(final ActiveMQComponent component, final Connection connection, final ProtocolManager protocol) { if (server == null) { throw new IllegalStateException("Unable to create connection, server hasn't finished starting up"); } ConnectionEntry entry = protocol.createConnectionEntry((Acceptor) component, connection); try { if (server.hasBrokerConnectionPlugins()) { server.callBrokerConnectionPlugins(plugin -> plugin.afterCreateConnection(entry.connection)); } } catch (ActiveMQException t) { logger.warn("Error executing afterCreateConnection plugin method: {}", t.getMessage(), t); throw new IllegalStateException(t.getMessage(), t.getCause()); } if (logger.isTraceEnabled()) { logger.trace("Connection created " + connection); } connections.put(connection.getID(), entry); connectionCountLatch.countUp(); totalConnectionCount.incrementAndGet(); } public RemotingConnection removeConnection(final Object remotingConnectionID) { ConnectionEntry entry = connections.remove(remotingConnectionID); if (entry != null) { logger.debug("RemotingServiceImpl::removing connection ID " + remotingConnectionID); connectionCountLatch.countDown(); return entry.connection; } else { logger.debug("The connectionID::" + remotingConnectionID + " was already removed by some other module"); return null; } } //...... }
- getConnectionCountLatch returns connectionCountLatch; connectionCreated method will execute connectionCountLatch.countUp(); removeConnection method will execute connectionCountLatch.countDown()
Summary
ConfigurationImpl defines two properties about gracefulShutdown, which are gracefulShutdown enabled (default is true) and gracefulShutdown timeout (default is - 1). ActiveMQServerImpl will read configuration. Getgracefulshutdown timeout() when remotingService is not null and configuration. Isgracefulshutdown enabled() is true. If timeout is - 1, remotingservi will be executed CE. Getconnectioncountlatch(). Await(), otherwise execute remotingService.getConnectionCountLatch().await(timeout)