You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ni...@apache.org on 2019/09/11 15:51:48 UTC
[activemq-artemis] branch master updated: ARTEMIS-2480 - Reloading
configuration can kill broker
This is an automated email from the ASF dual-hosted git repository.
nigrofranz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/activemq-artemis.git
The following commit(s) were added to refs/heads/master by this push:
new 42327a4 ARTEMIS-2480 - Reloading configuration can kill broker
new f3b984d This closes #2831
42327a4 is described below
commit 42327a490ad262df99828830c24be395be2c66ed
Author: Andy Taylor <an...@gmail.com>
AuthorDate: Tue Sep 10 09:45:25 2019 +0100
ARTEMIS-2480 - Reloading configuration can kill broker
https://issues.apache.org/jira/browse/ARTEMIS-2480
---
.../artemis/core/server/ActiveMQServerLogger.java | 8 ++
.../core/server/impl/ActiveMQServerImpl.java | 18 +++-
.../tests/integration/jms/RedeployTest.java | 78 ++++++++++++++
.../reload-test-autocreateaddress-reload.xml | 109 ++++++++++++++++++++
.../resources/reload-test-autocreateaddress.xml | 112 +++++++++++++++++++++
5 files changed, 322 insertions(+), 3 deletions(-)
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServerLogger.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServerLogger.java
index 8f76014..4952fce 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServerLogger.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServerLogger.java
@@ -2029,4 +2029,12 @@ public interface ActiveMQServerLogger extends BasicLogger {
@LogMessage(level = Logger.Level.WARN)
@Message(id = 224101, value = "Apache ActiveMQ Artemis is using a scheduled pool without remove on cancel policy, so a cancelled task could be not automatically removed from the work queue, it may also cause unbounded retention of cancelled tasks.", format = Message.Format.MESSAGE_FORMAT)
void scheduledPoolWithNoRemoveOnCancelPolicy();
+
+ @LogMessage(level = Logger.Level.INFO)
+ @Message(id = 224102, value = "unable to undeploy address {0} : reason {1}", format = Message.Format.MESSAGE_FORMAT)
+ void unableToUndeployAddress(SimpleString addressName, String reason);
+
+ @LogMessage(level = Logger.Level.INFO)
+ @Message(id = 224103, value = "unable to undeploy queue {0} : reason {1}", format = Message.Format.MESSAGE_FORMAT)
+ void unableToUndeployQueue(SimpleString queueName, String reason);
}
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java
index 9b5c3cb..881b01e 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java
@@ -3019,15 +3019,27 @@ public class ActiveMQServerImpl implements ActiveMQServer {
if (!addressesInConfig.contains(addressName.toString()) && addressSettings.getConfigDeleteAddresses() == DeletionPolicy.FORCE) {
for (Queue queue : listQueues(addressName)) {
ActiveMQServerLogger.LOGGER.undeployQueue(queue.getName());
- queue.deleteQueue(true);
+ try {
+ queue.deleteQueue(true);
+ } catch (Exception e) {
+ ActiveMQServerLogger.LOGGER.unableToUndeployQueue(addressName, e.getMessage());
+ }
}
ActiveMQServerLogger.LOGGER.undeployAddress(addressName);
- removeAddressInfo(addressName, null);
+ try {
+ removeAddressInfo(addressName, null);
+ } catch (Exception e) {
+ ActiveMQServerLogger.LOGGER.unableToUndeployAddress(addressName, e.getMessage());
+ }
} else if (addressSettings.getConfigDeleteQueues() == DeletionPolicy.FORCE) {
for (Queue queue : listConfiguredQueues(addressName)) {
if (!queuesInConfig.contains(queue.getName().toString())) {
ActiveMQServerLogger.LOGGER.undeployQueue(queue.getName());
- queue.deleteQueue(true);
+ try {
+ queue.deleteQueue(true);
+ } catch (Exception e) {
+ ActiveMQServerLogger.LOGGER.unableToUndeployQueue(addressName, e.getMessage());
+ }
}
}
}
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/RedeployTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/RedeployTest.java
index 643d103..e94f12b 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/RedeployTest.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/RedeployTest.java
@@ -42,11 +42,14 @@ import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.postoffice.Binding;
import org.apache.activemq.artemis.core.postoffice.QueueBinding;
import org.apache.activemq.artemis.core.security.Role;
+import org.apache.activemq.artemis.core.server.cluster.impl.MessageLoadBalancingType;
+import org.apache.activemq.artemis.core.server.cluster.impl.RemoteQueueBindingImpl;
import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.core.settings.impl.AddressFullMessagePolicy;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
+import org.apache.activemq.artemis.tests.unit.core.postoffice.impl.FakeQueue;
import org.apache.activemq.artemis.tests.util.Wait;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.utils.ReusableLatch;
@@ -56,6 +59,81 @@ import org.junit.Test;
public class RedeployTest extends ActiveMQTestBase {
@Test
+ /*
+ * This tests that the broker doesnt fall over when it tries to delete any autocreated addresses/queues in a clustered environment
+ * If the undeploy fails then bridges etc can stop working, we need to make sure if undeploy fails on anything the broker is still live
+ * */
+ public void testRedeployAutoCreateAddress() throws Exception {
+ Path brokerXML = getTestDirfile().toPath().resolve("broker.xml");
+ URL url1 = RedeployTest.class.getClassLoader().getResource("reload-test-autocreateaddress.xml");
+ URL url2 = RedeployTest.class.getClassLoader().getResource("reload-test-autocreateaddress-reload.xml");
+ Files.copy(url1.openStream(), brokerXML);
+
+ EmbeddedActiveMQ embeddedActiveMQ = new EmbeddedActiveMQ();
+ embeddedActiveMQ.setConfigResourcePath(brokerXML.toUri().toString());
+ embeddedActiveMQ.start();
+
+ ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
+ try (Connection connection = factory.createConnection()) {
+ Session session = connection.createSession();
+ Queue queue = session.createQueue("autoQueue");
+ MessageProducer producer = session.createProducer(queue);
+ producer.send(session.createTextMessage("text"));
+ connection.start();
+ MessageConsumer consumer = session.createConsumer(session.createQueue("autoQueue"));
+ Assert.assertNotNull("Address wasn't autocreated accordingly", consumer.receive(5000));
+ }
+
+ // this simulates a remote queue or other type being added that wouldnt get deleted, its not valid to have this happen but it can happen when addresses and queues are auto created in a clustered env
+ embeddedActiveMQ.getActiveMQServer().getPostOffice().addBinding(new RemoteQueueBindingImpl(5L,
+ new SimpleString("autoQueue"),
+ new SimpleString("uniqueName"),
+ new SimpleString("routingName"),
+ 6L,
+ null,
+ new FakeQueue(new SimpleString("foo"), 6L),
+ new SimpleString("bridge"),
+ 1,
+ MessageLoadBalancingType.OFF));
+
+ final ReusableLatch latch = new ReusableLatch(1);
+
+ Runnable tick = new Runnable() {
+ @Override
+ public void run() {
+ latch.countDown();
+ }
+ };
+
+ embeddedActiveMQ.getActiveMQServer().getReloadManager().setTick(tick);
+
+ try {
+ latch.await(10, TimeUnit.SECONDS);
+ Files.copy(url2.openStream(), brokerXML, StandardCopyOption.REPLACE_EXISTING);
+ brokerXML.toFile().setLastModified(System.currentTimeMillis() + 1000);
+ latch.setCount(1);
+ embeddedActiveMQ.getActiveMQServer().getReloadManager().setTick(tick);
+ latch.await(10, TimeUnit.SECONDS);
+
+ Assert.assertTrue(tryConsume());
+
+ factory = new ActiveMQConnectionFactory();
+ try (Connection connection = factory.createConnection()) {
+ Session session = connection.createSession();
+ Queue queue = session.createQueue("autoQueue");
+ MessageProducer producer = session.createProducer(queue);
+ producer.send(session.createTextMessage("text"));
+ connection.start();
+ MessageConsumer consumer = session.createConsumer(session.createQueue("autoQueue"));
+ Assert.assertNotNull("autoQueue redeployed accordingly", consumer.receive(5000));
+ }
+
+ } finally {
+ embeddedActiveMQ.stop();
+ }
+ }
+
+ @Test
public void testRedeploy() throws Exception {
Path brokerXML = getTestDirfile().toPath().resolve("broker.xml");
URL url1 = RedeployTest.class.getClassLoader().getResource("reload-test-jms.xml");
diff --git a/tests/integration-tests/src/test/resources/reload-test-autocreateaddress-reload.xml b/tests/integration-tests/src/test/resources/reload-test-autocreateaddress-reload.xml
new file mode 100644
index 0000000..23a703b
--- /dev/null
+++ b/tests/integration-tests/src/test/resources/reload-test-autocreateaddress-reload.xml
@@ -0,0 +1,109 @@
+<?xml version='1.0'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<configuration xmlns="urn:activemq"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:activemq /schema/artemis-configuration.xsd">
+
+ <core xmlns="urn:activemq:core">
+
+ <name>0.0.0.0</name>
+
+ <configuration-file-refresh-period>100</configuration-file-refresh-period>
+
+ <persistence-enabled>false</persistence-enabled>
+
+ <security-enabled>false</security-enabled>
+
+ <!-- this could be ASYNCIO or NIO
+ -->
+ <journal-type>NIO</journal-type>
+
+ <paging-directory>./data/paging</paging-directory>
+
+ <bindings-directory>./data/bindings</bindings-directory>
+
+ <journal-directory>./data/journal</journal-directory>
+
+ <large-messages-directory>./data/large-messages</large-messages-directory>
+
+ <journal-min-files>2</journal-min-files>
+
+ <journal-pool-files>-1</journal-pool-files>
+
+ <!--
+ This value was determined through a calculation.
+ Your system could perform 25 writes per millisecond
+ on the current journal configuration.
+ That translates as a sync write every 40000 nanoseconds
+ -->
+ <journal-buffer-timeout>40000</journal-buffer-timeout>
+
+
+ <acceptors>
+ <!-- Default ActiveMQ Artemis Acceptor. Multi-protocol adapter. Currently supports ActiveMQ Artemis Core, OpenWire, STOMP, AMQP, MQTT, and HornetQ Core. -->
+ <!-- performance tests have shown that openWire performs best with these buffer sizes -->
+ <acceptor name="artemis">tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576</acceptor>
+
+ <!-- AMQP Acceptor. Listens on default AMQP port for AMQP traffic.-->
+ <acceptor name="amqp">tcp://0.0.0.0:5672?protocols=AMQP</acceptor>
+
+ <!-- STOMP Acceptor. -->
+ <acceptor name="stomp">tcp://0.0.0.0:61613?protocols=STOMP</acceptor>
+
+ <!-- HornetQ Compatibility Acceptor. Enables HornetQ Core and STOMP for legacy HornetQ clients. -->
+ <acceptor name="hornetq">tcp://0.0.0.0:5445?protocols=HORNETQ,STOMP</acceptor>
+
+ <!-- MQTT Acceptor -->
+ <acceptor name="mqtt">tcp://0.0.0.0:1883?protocols=MQTT</acceptor>
+
+ </acceptors>
+
+
+ <security-settings>
+ <security-setting match="#">
+ <permission type="createNonDurableQueue" roles="a"/>
+ <permission type="deleteNonDurableQueue" roles="a"/>
+ <permission type="createDurableQueue" roles="a"/>
+ <permission type="deleteDurableQueue" roles="a"/>
+ <permission type="browse" roles="a"/>
+ <permission type="send" roles="a"/>
+ <!-- we need this otherwise ./artemis data imp wouldn't work -->
+ <permission type="manage" roles="a"/>
+ </security-setting>
+ </security-settings>
+
+ <address-settings>
+ <!--default for catch all-->
+ <address-setting match="#">
+ <auto-create-addresses>true</auto-create-addresses>
+ <auto-create-queues>true</auto-create-queues>
+ <dead-letter-address>DLQ</dead-letter-address>
+ <expiry-address>ExpiryQueue</expiry-address>
+ <redelivery-delay>0</redelivery-delay>
+ <max-size-bytes>10Mb</max-size-bytes>
+ <message-counter-history-day-limit>10</message-counter-history-day-limit>
+ <address-full-policy>BLOCK</address-full-policy>
+ <config-delete-addresses>FORCE</config-delete-addresses>
+ <config-delete-queues>FORCE</config-delete-queues>
+ </address-setting>
+ </address-settings>
+ </core>
+</configuration>
diff --git a/tests/integration-tests/src/test/resources/reload-test-autocreateaddress.xml b/tests/integration-tests/src/test/resources/reload-test-autocreateaddress.xml
new file mode 100644
index 0000000..92ce875
--- /dev/null
+++ b/tests/integration-tests/src/test/resources/reload-test-autocreateaddress.xml
@@ -0,0 +1,112 @@
+<?xml version='1.0'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<configuration xmlns="urn:activemq"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:activemq /schema/artemis-configuration.xsd">
+
+ <core xmlns="urn:activemq:core">
+
+ <name>0.0.0.0</name>
+
+ <configuration-file-refresh-period>100</configuration-file-refresh-period>
+
+ <persistence-enabled>false</persistence-enabled>
+
+ <security-enabled>false</security-enabled>
+
+ <!-- this could be ASYNCIO or NIO
+ -->
+ <journal-type>NIO</journal-type>
+
+ <paging-directory>./data/paging</paging-directory>
+
+ <bindings-directory>./data/bindings</bindings-directory>
+
+ <journal-directory>./data/journal</journal-directory>
+
+ <large-messages-directory>./data/large-messages</large-messages-directory>
+
+ <journal-min-files>2</journal-min-files>
+
+ <journal-pool-files>-1</journal-pool-files>
+
+ <!--
+ This value was determined through a calculation.
+ Your system could perform 25 writes per millisecond
+ on the current journal configuration.
+ That translates as a sync write every 40000 nanoseconds
+ -->
+ <journal-buffer-timeout>40000</journal-buffer-timeout>
+
+
+ <acceptors>
+ <!-- Default ActiveMQ Artemis Acceptor. Multi-protocol adapter. Currently supports ActiveMQ Artemis Core, OpenWire, STOMP, AMQP, MQTT, and HornetQ Core. -->
+ <!-- performance tests have shown that openWire performs best with these buffer sizes -->
+ <acceptor name="artemis">tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576</acceptor>
+
+ <!-- AMQP Acceptor. Listens on default AMQP port for AMQP traffic.-->
+ <acceptor name="amqp">tcp://0.0.0.0:5672?protocols=AMQP</acceptor>
+
+ <!-- STOMP Acceptor. -->
+ <acceptor name="stomp">tcp://0.0.0.0:61613?protocols=STOMP</acceptor>
+
+ <!-- HornetQ Compatibility Acceptor. Enables HornetQ Core and STOMP for legacy HornetQ clients. -->
+ <acceptor name="hornetq">tcp://0.0.0.0:5445?protocols=HORNETQ,STOMP</acceptor>
+
+ <!-- MQTT Acceptor -->
+ <acceptor name="mqtt">tcp://0.0.0.0:1883?protocols=MQTT</acceptor>
+
+ </acceptors>
+
+
+ <security-settings>
+ <security-setting match="#">
+ <permission type="createNonDurableQueue" roles="a"/>
+ <permission type="deleteNonDurableQueue" roles="a"/>
+ <permission type="createDurableQueue" roles="a"/>
+ <permission type="deleteDurableQueue" roles="a"/>
+ <permission type="browse" roles="a"/>
+ <permission type="send" roles="a"/>
+ <!-- we need this otherwise ./artemis data imp wouldn't work -->
+ <permission type="manage" roles="a"/>
+ </security-setting>
+ </security-settings>
+
+ <address-settings>
+ <!--default for catch all-->
+ <address-setting match="#">
+ <auto-create-addresses>true</auto-create-addresses>
+ <auto-create-queues>true</auto-create-queues>
+ <auto-delete-addresses>false</auto-delete-addresses>
+ <auto-delete-queues>false</auto-delete-queues>
+ <auto-delete-created-queues>false</auto-delete-created-queues>
+ <dead-letter-address>DLQ</dead-letter-address>
+ <expiry-address>ExpiryQueue</expiry-address>
+ <redelivery-delay>0</redelivery-delay>
+ <max-size-bytes>10Mb</max-size-bytes>
+ <message-counter-history-day-limit>10</message-counter-history-day-limit>
+ <address-full-policy>BLOCK</address-full-policy>
+ <config-delete-addresses>FORCE</config-delete-addresses>
+ <config-delete-queues>FORCE</config-delete-queues>
+ </address-setting>
+ </address-settings>
+ </core>
+</configuration>