ARTEMIS-1788 JDBC HA should use JDBC Network Timeout

JdbcNodeManager is configured to use the same network timeout
value of the journal and to validate all the timeout values
related to a correct HA behaviour.
This commit is contained in:
Francesco Nigro 2018-04-09 16:26:37 +02:00 committed by Clebert Suconic
parent 65be0f2041
commit 469d6baa93
4 changed files with 90 additions and 23 deletions

View File

@ -141,6 +141,9 @@ public abstract class AbstractJDBCDriver {
throw e; throw e;
} }
} }
if (this.networkTimeoutMillis >= 0 && this.networkTimeoutExecutor == null) {
logger.warn("Unable to set a network timeout on the JDBC connection: networkTimeoutExecutor is null");
}
if (this.networkTimeoutMillis >= 0 && this.networkTimeoutExecutor != null) { if (this.networkTimeoutMillis >= 0 && this.networkTimeoutExecutor != null) {
try { try {
connection.setNetworkTimeout(this.networkTimeoutExecutor, this.networkTimeoutMillis); connection.setNetworkTimeout(this.networkTimeoutExecutor, this.networkTimeoutMillis);

View File

@ -60,6 +60,7 @@ public final class JdbcNodeManager extends NodeManager {
ScheduledExecutorService scheduledExecutorService, ScheduledExecutorService scheduledExecutorService,
ExecutorFactory executorFactory, ExecutorFactory executorFactory,
IOCriticalErrorListener ioCriticalErrorListener) { IOCriticalErrorListener ioCriticalErrorListener) {
validateTimeoutConfiguration(configuration);
if (configuration.getDataSource() != null) { if (configuration.getDataSource() != null) {
final SQLProvider.Factory sqlProviderFactory; final SQLProvider.Factory sqlProviderFactory;
if (configuration.getSqlProviderFactory() != null) { if (configuration.getSqlProviderFactory() != null) {
@ -69,6 +70,7 @@ public final class JdbcNodeManager extends NodeManager {
} }
final String brokerId = java.util.UUID.randomUUID().toString(); final String brokerId = java.util.UUID.randomUUID().toString();
return usingDataSource(brokerId, return usingDataSource(brokerId,
configuration.getJdbcNetworkTimeout(),
configuration.getJdbcLockExpirationMillis(), configuration.getJdbcLockExpirationMillis(),
configuration.getJdbcLockRenewPeriodMillis(), configuration.getJdbcLockRenewPeriodMillis(),
configuration.getJdbcLockAcquisitionTimeoutMillis(), configuration.getJdbcLockAcquisitionTimeoutMillis(),
@ -82,6 +84,7 @@ public final class JdbcNodeManager extends NodeManager {
final SQLProvider sqlProvider = JDBCUtils.getSQLProvider(configuration.getJdbcDriverClassName(), configuration.getNodeManagerStoreTableName(), SQLProvider.DatabaseStoreType.NODE_MANAGER); final SQLProvider sqlProvider = JDBCUtils.getSQLProvider(configuration.getJdbcDriverClassName(), configuration.getNodeManagerStoreTableName(), SQLProvider.DatabaseStoreType.NODE_MANAGER);
final String brokerId = java.util.UUID.randomUUID().toString(); final String brokerId = java.util.UUID.randomUUID().toString();
return usingConnectionUrl(brokerId, return usingConnectionUrl(brokerId,
configuration.getJdbcNetworkTimeout(),
configuration.getJdbcLockExpirationMillis(), configuration.getJdbcLockExpirationMillis(),
configuration.getJdbcLockRenewPeriodMillis(), configuration.getJdbcLockRenewPeriodMillis(),
configuration.getJdbcLockAcquisitionTimeoutMillis(), configuration.getJdbcLockAcquisitionTimeoutMillis(),
@ -95,7 +98,8 @@ public final class JdbcNodeManager extends NodeManager {
} }
} }
static JdbcNodeManager usingDataSource(String brokerId, private static JdbcNodeManager usingDataSource(String brokerId,
int networkTimeoutMillis,
long lockExpirationMillis, long lockExpirationMillis,
long lockRenewPeriodMillis, long lockRenewPeriodMillis,
long lockAcquisitionTimeoutMillis, long lockAcquisitionTimeoutMillis,
@ -106,7 +110,13 @@ public final class JdbcNodeManager extends NodeManager {
ExecutorFactory executorFactory, ExecutorFactory executorFactory,
IOCriticalErrorListener ioCriticalErrorListener) { IOCriticalErrorListener ioCriticalErrorListener) {
return new JdbcNodeManager( return new JdbcNodeManager(
() -> JdbcSharedStateManager.usingDataSource(brokerId, lockExpirationMillis, maxAllowedMillisFromDbTime, dataSource, provider), () -> JdbcSharedStateManager.usingDataSource(brokerId,
networkTimeoutMillis,
executorFactory == null ? null : executorFactory.getExecutor(),
lockExpirationMillis,
maxAllowedMillisFromDbTime,
dataSource,
provider),
false, false,
lockRenewPeriodMillis, lockRenewPeriodMillis,
lockAcquisitionTimeoutMillis, lockAcquisitionTimeoutMillis,
@ -115,7 +125,8 @@ public final class JdbcNodeManager extends NodeManager {
ioCriticalErrorListener); ioCriticalErrorListener);
} }
public static JdbcNodeManager usingConnectionUrl(String brokerId, private static JdbcNodeManager usingConnectionUrl(String brokerId,
int networkTimeoutMillis,
long lockExpirationMillis, long lockExpirationMillis,
long lockRenewPeriodMillis, long lockRenewPeriodMillis,
long lockAcquisitionTimeoutMillis, long lockAcquisitionTimeoutMillis,
@ -127,7 +138,14 @@ public final class JdbcNodeManager extends NodeManager {
ExecutorFactory executorFactory, ExecutorFactory executorFactory,
IOCriticalErrorListener ioCriticalErrorListener) { IOCriticalErrorListener ioCriticalErrorListener) {
return new JdbcNodeManager( return new JdbcNodeManager(
() -> JdbcSharedStateManager.usingConnectionUrl(brokerId, lockExpirationMillis, maxAllowedMillisFromDbTime, jdbcUrl, driverClass, provider), () -> JdbcSharedStateManager.usingConnectionUrl(brokerId,
networkTimeoutMillis,
executorFactory == null ? null : executorFactory.getExecutor(),
lockExpirationMillis,
maxAllowedMillisFromDbTime,
jdbcUrl,
driverClass,
provider),
false, false,
lockRenewPeriodMillis, lockRenewPeriodMillis,
lockAcquisitionTimeoutMillis, lockAcquisitionTimeoutMillis,
@ -136,6 +154,28 @@ public final class JdbcNodeManager extends NodeManager {
ioCriticalErrorListener); ioCriticalErrorListener);
} }
private static void validateTimeoutConfiguration(DatabaseStorageConfiguration configuration) {
final long lockExpiration = configuration.getJdbcLockExpirationMillis();
if (lockExpiration <= 0) {
throw new IllegalArgumentException("jdbc-lock-expiration should be positive");
}
final long lockRenewPeriod = configuration.getJdbcLockRenewPeriodMillis();
if (lockRenewPeriod <= 0) {
throw new IllegalArgumentException("jdbc-lock-renew-period should be positive");
}
if (lockRenewPeriod >= lockExpiration) {
throw new IllegalArgumentException("jdbc-lock-renew-period should be < jdbc-lock-expiration");
}
final int networkTimeout = configuration.getJdbcNetworkTimeout();
if (networkTimeout >= 0) {
if (networkTimeout > lockExpiration) {
logger.warn("jdbc-network-timeout isn't properly configured: the recommended value is <= jdbc-lock-expiration");
}
} else {
logger.warn("jdbc-network-timeout isn't properly configured: the recommended value is <= jdbc-lock-expiration");
}
}
private JdbcNodeManager(Supplier<? extends SharedStateManager> sharedStateManagerFactory, private JdbcNodeManager(Supplier<? extends SharedStateManager> sharedStateManagerFactory,
boolean replicatedBackup, boolean replicatedBackup,
long lockRenewPeriodMillis, long lockRenewPeriodMillis,

View File

@ -24,6 +24,7 @@ import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.concurrent.Executor;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.apache.activemq.artemis.jdbc.store.drivers.AbstractJDBCDriver; import org.apache.activemq.artemis.jdbc.store.drivers.AbstractJDBCDriver;
@ -52,11 +53,14 @@ final class JdbcSharedStateManager extends AbstractJDBCDriver implements SharedS
private long timeDifferenceMillisFromDb = 0; private long timeDifferenceMillisFromDb = 0;
public static JdbcSharedStateManager usingDataSource(String holderId, public static JdbcSharedStateManager usingDataSource(String holderId,
int networkTimeout,
Executor networkTimeoutExecutor,
long locksExpirationMillis, long locksExpirationMillis,
long maxAllowedMillisFromDbTime, long maxAllowedMillisFromDbTime,
DataSource dataSource, DataSource dataSource,
SQLProvider provider) { SQLProvider provider) {
final JdbcSharedStateManager sharedStateManager = new JdbcSharedStateManager(holderId, locksExpirationMillis, maxAllowedMillisFromDbTime); final JdbcSharedStateManager sharedStateManager = new JdbcSharedStateManager(holderId, locksExpirationMillis, maxAllowedMillisFromDbTime);
sharedStateManager.setNetworkTimeout(networkTimeoutExecutor, networkTimeout);
sharedStateManager.setDataSource(dataSource); sharedStateManager.setDataSource(dataSource);
sharedStateManager.setSqlProvider(provider); sharedStateManager.setSqlProvider(provider);
try { try {
@ -73,7 +77,26 @@ final class JdbcSharedStateManager extends AbstractJDBCDriver implements SharedS
String jdbcConnectionUrl, String jdbcConnectionUrl,
String jdbcDriverClass, String jdbcDriverClass,
SQLProvider provider) { SQLProvider provider) {
return JdbcSharedStateManager.usingConnectionUrl(holderId,
-1,
null,
locksExpirationMillis,
maxAllowedMillisFromDbTime,
jdbcConnectionUrl,
jdbcDriverClass,
provider);
}
public static JdbcSharedStateManager usingConnectionUrl(String holderId,
int networkTimeout,
Executor networkTimeoutExecutor,
long locksExpirationMillis,
long maxAllowedMillisFromDbTime,
String jdbcConnectionUrl,
String jdbcDriverClass,
SQLProvider provider) {
final JdbcSharedStateManager sharedStateManager = new JdbcSharedStateManager(holderId, locksExpirationMillis, maxAllowedMillisFromDbTime); final JdbcSharedStateManager sharedStateManager = new JdbcSharedStateManager(holderId, locksExpirationMillis, maxAllowedMillisFromDbTime);
sharedStateManager.setNetworkTimeout(networkTimeoutExecutor, networkTimeout);
sharedStateManager.setJdbcConnectionUrl(jdbcConnectionUrl); sharedStateManager.setJdbcConnectionUrl(jdbcConnectionUrl);
sharedStateManager.setJdbcDriverClass(jdbcDriverClass); sharedStateManager.setJdbcDriverClass(jdbcDriverClass);
sharedStateManager.setSqlProvider(provider); sharedStateManager.setSqlProvider(provider);

View File

@ -456,6 +456,7 @@ To configure Apache ActiveMQ Artemis to use a database for persisting messages a
The JDBC network connection timeout in milliseconds. The default value The JDBC network connection timeout in milliseconds. The default value
is 20000 milliseconds (ie 20 seconds). is 20000 milliseconds (ie 20 seconds).
When using a shared store it is recommended to set it less then or equal to `jdbc-lock-expiration`.
- `jdbc-lock-renew-period` - `jdbc-lock-renew-period`