/*
* 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.
*/
package org.apache.activemq.artemis.tests.integration.cluster.bridge;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.config.BridgeConfiguration;
import org.apache.activemq.artemis.core.config.CoreQueueConfiguration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.cluster.impl.BridgeImpl;
import org.apache.activemq.artemis.tests.integration.cluster.util.MultiServerTestBase;
import org.junit.Test;
public class BridgeFailoverTest extends MultiServerTestBase {
@Test
public void testSimpleConnectOnMultipleNodes() throws Exception {
BridgeConfiguration bridgeConfiguration = new BridgeConfiguration();
String ORIGINAL_QUEUE = "noCluster.originalQueue";
String TARGET_QUEUE = "noCluster.targetQueue";
bridgeConfiguration.setHA(true);
List<String> connectors = new ArrayList<>();
connectors.add("target-4");
connectors.add("backup-4");
bridgeConfiguration.setName("Bridge-for-test");
bridgeConfiguration.setStaticConnectors(connectors);
bridgeConfiguration.setQueueName(ORIGINAL_QUEUE);
bridgeConfiguration.setForwardingAddress(TARGET_QUEUE);
bridgeConfiguration.setRetryInterval(100);
bridgeConfiguration.setConfirmationWindowSize(1);
bridgeConfiguration.setReconnectAttempts(-1);
servers[2].getConfiguration().getBridgeConfigurations().add(bridgeConfiguration);
for (ActiveMQServer server : servers) {
server.getConfiguration().getQueueConfigurations().add(new CoreQueueConfiguration().setAddress(ORIGINAL_QUEUE).setName(ORIGINAL_QUEUE));
server.getConfiguration().getQueueConfigurations().add(new CoreQueueConfiguration().setAddress(TARGET_QUEUE).setName(TARGET_QUEUE));
}
startServers();
// The server where the bridge source is configured at
ServerLocator locator = createLocator(false, 2);
ClientSessionFactory factory = addSessionFactory(locator.createSessionFactory());
ClientSession session = addClientSession(factory.createSession(false, false));
ClientProducer producer = addClientProducer(session.createProducer(ORIGINAL_QUEUE));
for (int i = 0; i < 100; i++) {
ClientMessage msg = session.createMessage(true);
msg.putIntProperty("i", i);
producer.send(msg);
}
session.commit();
ServerLocator locatorConsumer = createLocator(false, 4);
ClientSessionFactory factoryConsumer = addSessionFactory(locatorConsumer.createSessionFactory());
ClientSession sessionConsumer = addClientSession(factoryConsumer.createSession(false, false));
ClientConsumer consumer = sessionConsumer.createConsumer(TARGET_QUEUE);
sessionConsumer.start();
for (int i = 0; i < 100; i++) {
ClientMessage message = consumer.receive(10000);
assertNotNull(message);
message.acknowledge();
}
sessionConsumer.commit();
}
@Test
public void testFailoverOnBridgeNoRetryOnSameNode() throws Exception {
internalTestFailoverOnBridge(0);
}
@Test
public void testFailoverOnBridgeForeverRetryOnSameNode() throws Exception {
internalTestFailoverOnBridge(-1);
}
public void internalTestFailoverOnBridge(int retriesSameNode) throws Exception {
BridgeConfiguration bridgeConfiguration = new BridgeConfiguration();
String ORIGINAL_QUEUE = "noCluster.originalQueue";
String TARGET_QUEUE = "noCluster.targetQueue";
bridgeConfiguration.setHA(true);
List<String> connectors = new ArrayList<>();
connectors.add("target-4");
connectors.add("backup-4");
bridgeConfiguration.setName("Bridge-for-test");
bridgeConfiguration.setStaticConnectors(connectors);
bridgeConfiguration.setQueueName(ORIGINAL_QUEUE);
bridgeConfiguration.setForwardingAddress(TARGET_QUEUE);
bridgeConfiguration.setRetryInterval(100);
bridgeConfiguration.setConfirmationWindowSize(1);
bridgeConfiguration.setReconnectAttempts(-1);
bridgeConfiguration.setReconnectAttemptsOnSameNode(retriesSameNode);
bridgeConfiguration.setHA(true);
servers[2].getConfiguration().getBridgeConfigurations().add(bridgeConfiguration);
for (ActiveMQServer server : servers) {
server.getConfiguration().getQueueConfigurations().add(new CoreQueueConfiguration().setAddress(ORIGINAL_QUEUE).setName(ORIGINAL_QUEUE));
server.getConfiguration().getQueueConfigurations().add(new CoreQueueConfiguration().setAddress(TARGET_QUEUE).setName(TARGET_QUEUE));
}
startServers();
BridgeImpl bridge = (BridgeImpl) servers[2].getClusterManager().getBridges().get("Bridge-for-test");
assertNotNull(bridge);
long timeout = System.currentTimeMillis() + 5000;
while (bridge.getTargetNodeFromTopology() == null && timeout > System.currentTimeMillis()) {
Thread.sleep(100);
}
assertNotNull(bridge.getTargetNodeFromTopology());
// The server where the bridge source is configured at
ServerLocator locatorProducer = createLocator(false, 2);
ClientSessionFactory factory = addSessionFactory(locatorProducer.createSessionFactory());
ClientSession session = addClientSession(factory.createSession(false, false));
ClientProducer producer = addClientProducer(session.createProducer(ORIGINAL_QUEUE));
for (int i = 0; i < 100; i++) {
ClientMessage msg = session.createMessage(true);
msg.putIntProperty("i", i);
producer.send(msg);
}
session.commit();
ServerLocator locatorConsumer = createLocator(false, 4);
ClientSessionFactory factoryConsumer = addSessionFactory(locatorConsumer.createSessionFactory());
ClientSession sessionConsumer = addClientSession(factoryConsumer.createSession(false, false));
ClientConsumer consumer = sessionConsumer.createConsumer(TARGET_QUEUE);
sessionConsumer.start();
for (int i = 0; i < 100; i++) {
ClientMessage message = consumer.receive(10000);
assertNotNull(message);
message.acknowledge();
}
// We rollback as we will receive them again
sessionConsumer.rollback();
factoryConsumer.close();
sessionConsumer.close();
crashAndWaitForFailure(servers[4], locatorConsumer);
locatorConsumer.close();
assertTrue("Backup server didn't activate.", backupServers[4].waitForActivation(5, TimeUnit.SECONDS));
for (int i = 100; i < 200; i++) {
ClientMessage msg = session.createMessage(true);
msg.putIntProperty("i", i);
producer.send(msg);
}
session.commit();
locatorConsumer = createLocator(false, 9);
factoryConsumer = addSessionFactory(locatorConsumer.createSessionFactory());
sessionConsumer = addClientSession(factoryConsumer.createSession());
consumer = sessionConsumer.createConsumer(TARGET_QUEUE);
sessionConsumer.start();
for (int i = 0; i < 200; i++) {
ClientMessage message = consumer.receive(10000);
assertNotNull(message);
message.acknowledge();
}
sessionConsumer.commit();
}
@Test
public void testInitialConnectionNodeAlreadyDown() throws Exception {
BridgeConfiguration bridgeConfiguration = new BridgeConfiguration();
String ORIGINAL_QUEUE = "noCluster.originalQueue";
String TARGET_QUEUE = "noCluster.targetQueue";
bridgeConfiguration.setHA(true);
List<String> connectors = new ArrayList<>();
connectors.add("target-4");
connectors.add("backup-4");
bridgeConfiguration.setName("Bridge-for-test");
bridgeConfiguration.setStaticConnectors(connectors);
bridgeConfiguration.setQueueName(ORIGINAL_QUEUE);
bridgeConfiguration.setForwardingAddress(TARGET_QUEUE);
bridgeConfiguration.setRetryInterval(100);
bridgeConfiguration.setConfirmationWindowSize(1);
bridgeConfiguration.setReconnectAttempts(-1);
servers[2].getConfiguration().getBridgeConfigurations().add(bridgeConfiguration);
for (ActiveMQServer server : servers) {
server.getConfiguration().getQueueConfigurations().add(new CoreQueueConfiguration().setAddress(ORIGINAL_QUEUE).setName(ORIGINAL_QUEUE));
server.getConfiguration().getQueueConfigurations().add(new CoreQueueConfiguration().setAddress(TARGET_QUEUE).setName(TARGET_QUEUE));
}
startBackups(0, 1, 3, 4);
startServers(0, 1, 3, 4);
waitForTopology(servers[4], getNumberOfServers() - 1, getNumberOfServers() - 1);
crashAndWaitForFailure(servers[4], createLocator(false, 4));
waitForServerToStart(backupServers[4]);
startBackups(2);
startServers(2);
// The server where the bridge source is configured at
ServerLocator locator = createLocator(false, 2); // connecting to the backup
ClientSessionFactory factory = addSessionFactory(locator.createSessionFactory());
ClientSession session = addClientSession(factory.createSession(false, false));
ClientProducer producer = addClientProducer(session.createProducer(ORIGINAL_QUEUE));
for (int i = 0; i < 100; i++) {
ClientMessage msg = session.createMessage(true);
msg.putIntProperty("i", i);
producer.send(msg);
}
session.commit();
ServerLocator locatorConsumer = createLocator(false, 9);
ClientSessionFactory factoryConsumer = addSessionFactory(locatorConsumer.createSessionFactory());
ClientSession sessionConsumer = addClientSession(factoryConsumer.createSession(false, false));
ClientConsumer consumer = sessionConsumer.createConsumer(TARGET_QUEUE);
sessionConsumer.start();
for (int i = 0; i < 100; i++) {
ClientMessage message = consumer.receive(10000);
assertNotNull(message);
message.acknowledge();
}
sessionConsumer.commit();
}
}