This is an automated email from the ASF dual-hosted git repository. orudyy pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git
commit 6e395612a604fa747cfe9353ab5c86e3b752a9fb Author: Tomas Vavricka <[email protected]> AuthorDate: Fri Jul 17 11:45:28 2020 +0000 QPID-8456: [Broker-J] Configurable shutdown timeout This closes #49 --- .../qpid/server/model/AbstractSystemConfig.java | 62 ------------------- .../java/org/apache/qpid/server/model/Broker.java | 10 +++- .../org/apache/qpid/server/model/BrokerImpl.java | 70 ++++++++++++++++++---- .../src/main/java/resources/editBroker.html | 13 ++++ .../java/resources/js/qpid/management/Broker.js | 1 + .../resources/js/qpid/management/editBroker.js | 2 +- .../src/main/java/resources/showBroker.html | 4 ++ .../Java-Broker-Management-Managing-Broker.xml | 4 ++ 8 files changed, 92 insertions(+), 74 deletions(-) diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java b/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java index ca174f0..cfa740a 100644 --- a/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java +++ b/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java @@ -27,7 +27,6 @@ import java.io.Reader; import java.net.MalformedURLException; import java.net.URL; import java.security.Principal; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -35,18 +34,11 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import javax.security.auth.Subject; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.configuration.store.ManagementModeStoreHandler; @@ -71,10 +63,7 @@ import org.apache.qpid.server.util.urlstreamhandler.classpath.Handler; public abstract class AbstractSystemConfig<X extends SystemConfig<X>> extends AbstractConfiguredObject<X> implements SystemConfig<X>, DynamicModel { - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractSystemConfig.class); - private static final UUID SYSTEM_ID = new UUID(0l, 0l); - private static final long SHUTDOWN_TIMEOUT = 30000l; private final Principal _systemPrincipal; @@ -111,8 +100,6 @@ public abstract class AbstractSystemConfig<X extends SystemConfig<X>> @ManagedAttributeField private String _defaultContainerType; - private final Thread _shutdownHook = new Thread(new ShutdownService(), "QpidBrokerShutdownHook"); - static { Handler.register(); @@ -152,22 +139,6 @@ public abstract class AbstractSystemConfig<X extends SystemConfig<X>> } @Override - protected ListenableFuture<Void> beforeClose() - { - try - { - boolean removed = Runtime.getRuntime().removeShutdownHook(_shutdownHook); - LOGGER.debug("Removed shutdown hook : {}", removed); - } - catch(IllegalStateException ise) - { - //ignore, means the JVM is already shutting down - } - - return super.beforeClose(); - } - - @Override protected ListenableFuture<Void> onClose() { final TaskExecutor taskExecutor = getTaskExecutor(); @@ -244,11 +215,6 @@ public abstract class AbstractSystemConfig<X extends SystemConfig<X>> @Override protected void onOpen() { - super.onOpen(); - - Runtime.getRuntime().addShutdownHook(_shutdownHook); - LOGGER.debug("Added shutdown hook"); - _configurationStore = createStoreObject(); if (isManagementMode()) @@ -597,32 +563,4 @@ public abstract class AbstractSystemConfig<X extends SystemConfig<X>> return null; } } - - private class ShutdownService implements Runnable - { - @Override - public void run() - { - Subject.doAs(getSystemTaskSubject("Shutdown"), - new PrivilegedAction<Object>() - { - @Override - public Object run() - { - LOGGER.debug("Shutdown hook initiating close"); - ListenableFuture<Void> closeResult = closeAsync(); - try - { - closeResult.get(SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS); - } - catch (InterruptedException | ExecutionException | TimeoutException e) - { - LOGGER.warn("Attempting to cleanly shutdown took too long, exiting immediately", e); - } - return null; - } - }); - } - } - } diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java b/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java index 62e2519..4e45159 100644 --- a/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java +++ b/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java @@ -62,6 +62,7 @@ public interface Broker<X extends Broker<X>> extends ConfiguredObject<X>, EventL String QPID_AMQP_PORT = "qpid.amqp_port"; String QPID_HTTP_PORT = "qpid.http_port"; String QPID_DOCUMENTATION_URL = "qpid.helpURL"; + String BROKER_SHUTDOWN_TIMEOUT = "broker.shutdownTimeout"; String BROKER_STATISTICS_REPORING_PERIOD = "broker.statisticsReportingPeriod"; String NETWORK_BUFFER_SIZE = "qpid.broker.networkBufferSize"; @@ -123,6 +124,9 @@ public interface Broker<X extends Broker<X>> extends ConfiguredObject<X>, EventL @ManagedContextDefault(name = QPID_DOCUMENTATION_URL) String DEFAULT_DOCUMENTATION_URL = "http://qpid.apache.org/releases/qpid-broker-j-${qpid.version}/book/"; + @ManagedContextDefault(name = BROKER_SHUTDOWN_TIMEOUT) + int DEFAULT_BROKER_SHUTDOWN_TIMEOUT = 30; + @ManagedContextDefault(name = BROKER_STATISTICS_REPORING_PERIOD) int DEFAULT_STATISTICS_REPORTING_PERIOD = 0; @@ -146,11 +150,15 @@ public interface Broker<X extends Broker<X>> extends ConfiguredObject<X>, EventL @DerivedAttribute int getNumberOfCores(); + @ManagedAttribute( defaultValue = "${" + BROKER_SHUTDOWN_TIMEOUT + "}", description = "Broker shutdown timeout in seconds (disabled if 0)." + + " If clean shutdown takes more than shutdown timeout, broker exits immediately.") + int getShutdownTimeout(); + @ManagedAttribute( defaultValue = "${" + BROKER_STATISTICS_REPORING_PERIOD + "}", description = "Period (in seconds) of the statistic report.") int getStatisticsReportingPeriod(); @ManagedContextDefault( name = "broker.housekeepingThreadCount") - public static final int DEFAULT_HOUSEKEEPING_THREAD_COUNT = 2; + int DEFAULT_HOUSEKEEPING_THREAD_COUNT = 2; String QPID_BROKER_HOUSEKEEPING_CHECK_PERIOD = "qpid.broker.housekeepingCheckPeriod"; @ManagedContextDefault(name = QPID_BROKER_HOUSEKEEPING_CHECK_PERIOD) diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/BrokerImpl.java b/broker-core/src/main/java/org/apache/qpid/server/model/BrokerImpl.java index 085628d..7d0b77f 100644 --- a/broker-core/src/main/java/org/apache/qpid/server/model/BrokerImpl.java +++ b/broker-core/src/main/java/org/apache/qpid/server/model/BrokerImpl.java @@ -38,9 +38,11 @@ import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicLong; import java.util.regex.Pattern; @@ -72,7 +74,6 @@ import org.apache.qpid.server.security.AccessControl; import org.apache.qpid.server.security.CompoundAccessControl; import org.apache.qpid.server.security.Result; import org.apache.qpid.server.security.SubjectFixedResultAccessControl; -import org.apache.qpid.server.security.SubjectFixedResultAccessControl.ResultCalculator; import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; import org.apache.qpid.server.security.auth.SocketConnectionMetaData; import org.apache.qpid.server.security.auth.SocketConnectionPrincipal; @@ -102,14 +103,10 @@ public class BrokerImpl extends AbstractContainer<BrokerImpl> implements Broker< public static final String MANAGEMENT_MODE_AUTHENTICATION = "MANAGEMENT_MODE_AUTHENTICATION"; - private final AccessControl _systemUserAllowed = new SubjectFixedResultAccessControl(new ResultCalculator() - { - @Override - public Result getResult(final Subject subject) - { - return isSystemSubject(subject) ? Result.ALLOWED : Result.DEFER; - } - }, Result.DEFER); + private final Thread _shutdownHook = new Thread(new ShutdownService(), "QpidBrokerShutdownHook"); + + private final AccessControl _systemUserAllowed = new SubjectFixedResultAccessControl(subject -> + isSystemSubject(subject) ? Result.ALLOWED : Result.DEFER, Result.DEFER); private final BrokerPrincipal _principal; @@ -124,6 +121,8 @@ public class BrokerImpl extends AbstractContainer<BrokerImpl> implements Broker< private final AtomicLong _maximumMessageSize = new AtomicLong(); @ManagedAttributeField + private int _shutdownTimeout; + @ManagedAttributeField private int _statisticsReportingPeriod; @ManagedAttributeField private boolean _messageCompressionEnabled; @@ -531,6 +530,12 @@ public class BrokerImpl extends AbstractContainer<BrokerImpl> implements Broker< } @Override + public int getShutdownTimeout() + { + return _shutdownTimeout; + } + + @Override public int getStatisticsReportingPeriod() { return _statisticsReportingPeriod; @@ -611,6 +616,9 @@ public class BrokerImpl extends AbstractContainer<BrokerImpl> implements Broker< { super.onOpen(); + Runtime.getRuntime().addShutdownHook(_shutdownHook); + LOGGER.debug("Added shutdown hook"); + PreferencesRoot preferencesRoot = (SystemConfig) getParent(); _preferenceStore = preferencesRoot.createPreferenceStore(); @@ -703,7 +711,16 @@ public class BrokerImpl extends AbstractContainer<BrokerImpl> implements Broker< @Override protected ListenableFuture<Void> beforeClose() { - _brokerLoggersToClose = new ArrayList(getChildren(BrokerLogger.class)); + try + { + final boolean removed = Runtime.getRuntime().removeShutdownHook(_shutdownHook); + LOGGER.debug("Removed shutdown hook: " + removed); + } + catch(IllegalStateException ise) + { + LOGGER.debug("JVM is already shutting down", ise); + } + _brokerLoggersToClose = new ArrayList<>(getChildren(BrokerLogger.class)); return super.beforeClose(); } @@ -1294,4 +1311,37 @@ public class BrokerImpl extends AbstractContainer<BrokerImpl> implements Broker< } } + private class ShutdownService implements Runnable + { + @Override + public void run() + { + Subject.doAs(getSystemTaskSubject("Shutdown"), (PrivilegedAction<Object>) () -> + { + LOGGER.debug("Shutdown hook initiating close"); + waitForBrokerShutdown(); + return null; + }); + } + + private void waitForBrokerShutdown() + { + final ListenableFuture<Void> closeResult = _parent.closeAsync(); + try + { + if (_shutdownTimeout < 1) + { + closeResult.get(); + } + else + { + closeResult.get(_shutdownTimeout, TimeUnit.SECONDS); + } + } + catch (InterruptedException | ExecutionException | TimeoutException e) + { + LOGGER.warn("Attempting to cleanly shutdown took too long, exiting immediately", e); + } + } + } } diff --git a/broker-plugins/management-http/src/main/java/resources/editBroker.html b/broker-plugins/management-http/src/main/java/resources/editBroker.html index b5120c6..8a26dff 100644 --- a/broker-plugins/management-http/src/main/java/resources/editBroker.html +++ b/broker-plugins/management-http/src/main/java/resources/editBroker.html @@ -37,6 +37,19 @@ </div> </div> <div class="clear"> + <div class="formLabel-labelCell tableContainer-labelCell">Shutdown timeout (s):</div> + <div class="formLabel-controlCell tableContainer-valueCell"> + <input type="text" id="editBroker.shutdownTimeout" + data-dojo-type="dijit/form/ValidationTextBox" + data-dojo-props=" + name: 'shutdownTimeout', + trim: true, + placeholder: 'Time in seconds', + label: 'Shutdown timeout (s):', + promptMessage: 'Broker shutdown timeout in seconds (disabled if 0).<br>If clean shutdown takes more than shutdown timeout, broker exits immediately.'" /> + </div> + </div> + <div class="clear"> <div class="formLabel-labelCell tableContainer-labelCell">Statistics reporting period (s):</div> <div class="formLabel-controlCell tableContainer-valueCell"> <input type="text" id="editBroker.statisticsReportingPeriod" diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js index f0f8be1..98c29fd 100644 --- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js +++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js @@ -96,6 +96,7 @@ define(["dojo/parser", "productVersion", "processPid", "modelVersion", + "shutdownTimeout", "statisticsReportingPeriod", "statisticsReportingResetEnabled", "confidentialConfigurationEncryptionProvider"]; diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/editBroker.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/editBroker.js index be8a67f..58b56ee 100644 --- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/editBroker.js +++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/editBroker.js @@ -59,7 +59,7 @@ define(["dojox/html/entities", util, template) { - var numericFieldNames = ["statisticsReportingPeriod"]; + var numericFieldNames = ["shutdownTimeout", "statisticsReportingPeriod"]; var brokerEditor = { init: function () diff --git a/broker-plugins/management-http/src/main/java/resources/showBroker.html b/broker-plugins/management-http/src/main/java/resources/showBroker.html index f23f2dd..956e415 100644 --- a/broker-plugins/management-http/src/main/java/resources/showBroker.html +++ b/broker-plugins/management-http/src/main/java/resources/showBroker.html @@ -46,6 +46,10 @@ <div class="formLabel-labelCell">PID:</div> <div id="brokerAttribute.processPid"></div> </div> + <div id="brokerAttribute.shutdownTimeout.container" class="clear"> + <div class="formLabel-labelCell">Shutdown timeout (s):</div> + <div id="brokerAttribute.shutdownTimeout"></div> + </div> <div id="brokerAttribute.confidentialConfigurationEncryptionProvider.container" class="clear"> <div class="formLabel-labelCell">Config Encryption:</div> <div id="brokerAttribute.confidentialConfigurationEncryptionProvider"></div> diff --git a/doc/java-broker/src/docbkx/management/managing/Java-Broker-Management-Managing-Broker.xml b/doc/java-broker/src/docbkx/management/managing/Java-Broker-Management-Managing-Broker.xml index 6194209..a4cae77 100644 --- a/doc/java-broker/src/docbkx/management/managing/Java-Broker-Management-Managing-Broker.xml +++ b/doc/java-broker/src/docbkx/management/managing/Java-Broker-Management-Managing-Broker.xml @@ -35,6 +35,10 @@ environments that have many.</para> </listitem> <listitem> + <para><emphasis>Shutdown timeout</emphasis>. Broker shutdown timeout in seconds (disabled if 0). If clean + shutdown takes more than shutdown timeout, broker exits immediately.</para> + </listitem> + <listitem> <para><emphasis>Confidential configuration encryption provider</emphasis>. The name of the provider used to encrypt passwords and other secrets within the configuration. See <xref linkend="Java-Broker-Security-Configuration-Encryption"/>.</para> </listitem> --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
