ARTEMIS-5085 use retry parameters on initial connection

When the Core client attempts to create the initial connection to a
broker when initialConnectAttempts > 1 it will adhere to retryInterval,
but it will ignore retryIntervalMultiplier & maxRetryInterval. This
commit fixes that so that these parameters are taken into account.
This commit is contained in:
Justin Bertram 2024-10-02 13:58:16 -05:00 committed by Timothy Bish
parent 821005ab6e
commit 8a1f9e8874
4 changed files with 58 additions and 14 deletions

View File

@ -764,7 +764,7 @@ public class ClientSessionFactoryImpl implements ClientSessionFactoryInternal, C
failoverRetries++;
if (failoverRetryPredicate.test(false, failoverRetries)) {
waitForRetry(failoverRetryInterval);
failoverRetryInterval = getNextRetryInterval(failoverRetryInterval);
failoverRetryInterval = serverLocator.getNextRetryInterval(failoverRetryInterval, retryIntervalMultiplier, maxRetryInterval);
}
}
}
@ -989,7 +989,7 @@ public class ClientSessionFactoryImpl implements ClientSessionFactoryInternal, C
if (waitForRetry(interval))
return count;
interval = getNextRetryInterval(interval);
interval = serverLocator.getNextRetryInterval(interval, retryIntervalMultiplier, maxRetryInterval);
} else {
logger.debug("Could not connect to any server. Didn't have reconnection configured on the ClientSessionFactory");
return count;
@ -1000,17 +1000,6 @@ public class ClientSessionFactoryImpl implements ClientSessionFactoryInternal, C
return count;
}
private long getNextRetryInterval(long retryInterval) {
// Exponential back-off
long nextRetryInterval = (long) (retryInterval * retryIntervalMultiplier);
if (nextRetryInterval > maxRetryInterval) {
nextRetryInterval = maxRetryInterval;
}
return nextRetryInterval;
}
@Override
public boolean waitForRetry(long interval) {
try {

View File

@ -687,6 +687,7 @@ public final class ServerLocatorImpl implements ServerLocatorInternal, Discovery
boolean topologyArrayTried = !config.useTopologyForLoadBalancing || topologyArray == null || topologyArray.length == 0;
boolean staticTried = false;
boolean shouldTryStatic = useInitConnector();
long interval = config.retryInterval;
while (retry && !isClosed()) {
retry = false;
@ -746,9 +747,10 @@ public final class ServerLocatorImpl implements ServerLocatorInternal, Discovery
}
}
}
if (factory.waitForRetry(config.retryInterval)) {
if (factory.waitForRetry(interval)) {
throw ActiveMQClientMessageBundle.BUNDLE.cannotConnectToServers();
}
interval = getNextRetryInterval(interval, config.retryIntervalMultiplier, config.maxRetryInterval);
retry = true;
} else {
throw e;
@ -779,6 +781,18 @@ public final class ServerLocatorImpl implements ServerLocatorInternal, Discovery
return factory;
}
@Override
public long getNextRetryInterval(long retryInterval, double retryIntervalMultiplier, long maxRetryInterval) {
// Exponential back-off
long nextRetryInterval = (long) (retryInterval * retryIntervalMultiplier);
if (nextRetryInterval > maxRetryInterval) {
nextRetryInterval = maxRetryInterval;
}
return nextRetryInterval;
}
private void executeDiscovery() throws ActiveMQException {
boolean discoveryOK = false;
boolean retryDiscovery = false;

View File

@ -94,4 +94,6 @@ public interface ServerLocatorInternal extends ServerLocator {
int getConnectorsSize();
Pair<TransportConfiguration, TransportConfiguration> selectNextConnectorPair();
long getNextRetryInterval(long retryInterval, double retryIntervalMultiplier, long maxRetryInterval);
}

View File

@ -19,6 +19,7 @@ package org.apache.activemq.artemis.tests.integration.client;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
@ -75,4 +76,42 @@ public class InitialConnectionTest extends ActiveMQTestBase {
long timeEnd = System.currentTimeMillis();
assertTrue(timeEnd - timeStart >= 500, "3 connectors, at 100 milliseconds each try, initialConnectAttempt=2, it should have waited at least 600 (- 100 from the last try that we don't actually wait, just throw ) milliseconds");
}
@Test
public void testRetryIntervalMultiplier() {
int interval = 100;
double multiplier = 10.0;
int attempts = 3;
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61610?retryInterval=" + interval + "&retryIntervalMultiplier=" + multiplier + "&initialConnectAttempts=" + attempts);
long timeStart = System.currentTimeMillis();
try {
connectionFactory.createConnection();
fail("Creating connection here should have failed");
} catch (JMSException e) {
// expected
}
long duration = System.currentTimeMillis() - timeStart;
long toWait = 1100;
assertTrue(duration >= toWait, "Waited only " + duration + "ms, but should have waiting " + toWait);
}
@Test
public void testMaxRetryInterval() {
int interval = 100;
double multiplier = 50.0;
int attempts = 3;
int maxInterval = 1000;
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61610?retryInterval=" + interval + "&retryIntervalMultiplier=" + multiplier + "&initialConnectAttempts=" + attempts + "&maxRetryInterval=" + maxInterval);
long timeStart = System.currentTimeMillis();
try {
connectionFactory.createConnection();
fail("Creating connection here should have failed");
} catch (JMSException e) {
// expected
}
long duration = System.currentTimeMillis() - timeStart;
long toWait = 1100;
assertTrue(duration >= toWait, "Waited only " + duration + "ms, but should have waited " + toWait);
assertTrue(duration <= toWait + 500, "Waited " + duration + "ms, but should have only waited " + (toWait + 500));
}
}