You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by or...@apache.org on 2020/09/12 21:30:34 UTC

[qpid-broker-j] 01/17: QPID-8456: [Broker-J] Configurable shutdown timeout

This is an automated email from the ASF dual-hosted git repository.

orudyy pushed a commit to branch 8.0.x
in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git

commit 34e7428fc33fc6c693fef9e544f105a5cd0fb96e
Author: Tomas Vavricka <to...@deutsche-boerse.com>
AuthorDate: Fri Jul 17 11:45:28 2020 +0000

    QPID-8456: [Broker-J] Configurable shutdown timeout
    
    This closes #49
    
    (cherry picked from commit 6e395612a604fa747cfe9353ab5c86e3b752a9fb)
---
 .../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: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org