ARTEMIS-1124 JDBC Network Timeout configuration

(cherry picked from commit a639774b54)
This commit is contained in:
Francesco Nigro 2017-04-20 12:43:40 +02:00
parent ec085b8ea0
commit 87bde15f38
9 changed files with 96 additions and 6 deletions

View File

@ -16,6 +16,8 @@
*/
package org.apache.activemq.artemis.api.config;
import java.util.concurrent.TimeUnit;
import org.apache.activemq.artemis.ArtemisConstants;
import org.apache.activemq.artemis.api.core.SimpleString;
@ -429,6 +431,8 @@ public final class ActiveMQDefaultConfiguration {
// Default large messages table name, used with Database storage type
private static final String DEFAULT_PAGE_STORE_TABLE_NAME = "PAGE_STORE";
private static final int DEFAULT_JDBC_NETWORK_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(20);
// Default period to wait between connection TTL checks
public static final long DEFAULT_CONNECTION_TTL_CHECK_INTERVAL = 2000;
@ -1172,6 +1176,10 @@ public final class ActiveMQDefaultConfiguration {
return DEFAULT_PAGE_STORE_TABLE_NAME;
}
public static int getDefaultJdbcNetworkTimeout() {
return DEFAULT_JDBC_NETWORK_TIMEOUT;
}
public static long getDefaultConnectionTtlCheckInterval() {
return DEFAULT_CONNECTION_TTL_CHECK_INTERVAL;
}

View File

@ -26,6 +26,7 @@ import java.sql.SQLWarning;
import java.sql.Statement;
import java.util.Arrays;
import java.util.Properties;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -51,18 +52,28 @@ public abstract class AbstractJDBCDriver {
private DataSource dataSource;
private Executor networkTimeoutExecutor;
private int networkTimeoutMillis;
public AbstractJDBCDriver() {
this.networkTimeoutExecutor = null;
this.networkTimeoutMillis = -1;
}
public AbstractJDBCDriver(SQLProvider sqlProvider, String jdbcConnectionUrl, String jdbcDriverClass) {
this.jdbcConnectionUrl = jdbcConnectionUrl;
this.jdbcDriverClass = jdbcDriverClass;
this.sqlProvider = sqlProvider;
this.networkTimeoutExecutor = null;
this.networkTimeoutMillis = -1;
}
public AbstractJDBCDriver(DataSource dataSource, SQLProvider provider) {
this.dataSource = dataSource;
this.sqlProvider = provider;
this.networkTimeoutExecutor = null;
this.networkTimeoutMillis = -1;
}
public void start() throws SQLException {
@ -76,6 +87,8 @@ public abstract class AbstractJDBCDriver {
public AbstractJDBCDriver(Connection connection, SQLProvider sqlProvider) {
this.connection = connection;
this.sqlProvider = sqlProvider;
this.networkTimeoutExecutor = null;
this.networkTimeoutMillis = -1;
}
public void stop() throws SQLException {
@ -127,6 +140,17 @@ public abstract class AbstractJDBCDriver {
throw e;
}
}
if (this.networkTimeoutMillis >= 0 && this.networkTimeoutExecutor != null) {
try {
connection.setNetworkTimeout(this.networkTimeoutExecutor, this.networkTimeoutMillis);
} catch (SQLException e) {
logger.warn(JDBCUtils.appendSQLExceptionDetails(new StringBuilder(), e));
ActiveMQJournalLogger.LOGGER.warn("Unable to set a network timeout on the JDBC connection");
} catch (Throwable throwable) {
//it included SecurityExceptions and UnsupportedOperationException
logger.warn("Unable to set a network timeout on the JDBC connection", throwable);
}
}
}
}
@ -240,4 +264,9 @@ public abstract class AbstractJDBCDriver {
this.dataSource = dataSource;
}
public void setNetworkTimeout(Executor executor, int milliseconds) {
this.networkTimeoutExecutor = executor;
this.networkTimeoutMillis = milliseconds;
}
}

View File

@ -101,6 +101,14 @@ public class JDBCSequentialFileFactory implements SequentialFileFactory, ActiveM
return dbDriver;
}
/**
* @see Connection#setNetworkTimeout(Executor, int)
**/
public JDBCSequentialFileFactory setNetworkTimeout(Executor executor, int milliseconds) {
this.dbDriver.setNetworkTimeout(executor, milliseconds);
return this;
}
@Override
public SequentialFileFactory setDatasync(boolean enabled) {
return this;

View File

@ -40,6 +40,8 @@ public class DatabaseStorageConfiguration implements StoreConfiguration {
private SQLProvider.Factory sqlProviderFactory;
private int jdbcNetworkTimeout = ActiveMQDefaultConfiguration.getDefaultJdbcNetworkTimeout();
@Override
public StoreType getStoreType() {
return StoreType.DATABASE;
@ -125,4 +127,12 @@ public class DatabaseStorageConfiguration implements StoreConfiguration {
public void setSqlProvider(SQLProvider.Factory sqlProviderFactory) {
this.sqlProviderFactory = sqlProviderFactory;
}
public int getJdbcNetworkTimeout() {
return this.jdbcNetworkTimeout;
}
public void setJdbcNetworkTimeout(int jdbcNetworkTimeout) {
this.jdbcNetworkTimeout = jdbcNetworkTimeout;
}
}

View File

@ -1159,6 +1159,7 @@ public final class FileConfigurationParser extends XMLConfigurationUtil {
conf.setPageStoreTableName(getString(storeNode, "page-store-table-name", conf.getPageStoreTableName(), Validators.NO_CHECK));
conf.setJdbcConnectionUrl(getString(storeNode, "jdbc-connection-url", conf.getJdbcConnectionUrl(), Validators.NO_CHECK));
conf.setJdbcDriverClassName(getString(storeNode, "jdbc-driver-class-name", conf.getJdbcDriverClassName(), Validators.NO_CHECK));
conf.setJdbcNetworkTimeout(getInteger(storeNode, "jdbc-network-timeout", conf.getJdbcNetworkTimeout(), Validators.NO_CHECK));
return conf;
}

View File

@ -117,6 +117,10 @@ public class PagingStoreFactoryDatabase implements PagingStoreFactory {
String driverClassName = dbConf.getJdbcDriverClassName();
pagingFactoryFileFactory = new JDBCSequentialFileFactory(dbConf.getJdbcConnectionUrl(), driverClassName, JDBCUtils.getSQLProvider(driverClassName, pageStoreTableNamePrefix, SQLProvider.DatabaseStoreType.PAGE), executorFactory.getExecutor(), criticalErrorListener);
}
final int jdbcNetworkTimeout = dbConf.getJdbcNetworkTimeout();
if (jdbcNetworkTimeout >= 0) {
pagingFactoryFileFactory.setNetworkTimeout(this.executorFactory.getExecutor(), jdbcNetworkTimeout);
}
pagingFactoryFileFactory.start();
started = true;
}
@ -224,8 +228,12 @@ public class PagingStoreFactoryDatabase implements PagingStoreFactory {
} else {
sqlProvider = JDBCUtils.getSQLProvider(dbConf.getJdbcDriverClassName(), getTableNameForGUID(directoryName), SQLProvider.DatabaseStoreType.PAGE);
}
return new JDBCSequentialFileFactory(pagingFactoryFileFactory.getDbDriver().getConnection(), sqlProvider, executorFactory.getExecutor(), criticalErrorListener);
final JDBCSequentialFileFactory fileFactory = new JDBCSequentialFileFactory(pagingFactoryFileFactory.getDbDriver().getConnection(), sqlProvider, executorFactory.getExecutor(), criticalErrorListener);
final int jdbcNetworkTimeout = dbConf.getJdbcNetworkTimeout();
if (jdbcNetworkTimeout >= 0) {
fileFactory.setNetworkTimeout(this.executorFactory.getExecutor(), jdbcNetworkTimeout);
}
return fileFactory;
}
private String getTableNameForGUID(String guid) {

View File

@ -55,8 +55,10 @@ public class JDBCJournalStorageManager extends JournalStorageManager {
@Override
protected synchronized void init(Configuration config, IOCriticalErrorListener criticalErrorListener) {
try {
DatabaseStorageConfiguration dbConf = (DatabaseStorageConfiguration) config.getStoreConfiguration();
final DatabaseStorageConfiguration dbConf = (DatabaseStorageConfiguration) config.getStoreConfiguration();
final JDBCJournalImpl bindingsJournal;
final JDBCJournalImpl messageJournal;
final JDBCSequentialFileFactory largeMessagesFactory;
if (dbConf.getDataSource() != null) {
SQLProvider.Factory sqlProviderFactory = dbConf.getSqlProviderFactory();
if (sqlProviderFactory == null) {
@ -71,6 +73,19 @@ public class JDBCJournalStorageManager extends JournalStorageManager {
messageJournal = new JDBCJournalImpl(dbConf.getJdbcConnectionUrl(), driverClassName, JDBCUtils.getSQLProvider(driverClassName, dbConf.getMessageTableName(), SQLProvider.DatabaseStoreType.MESSAGE_JOURNAL), scheduledExecutorService, executorFactory.getExecutor(), criticalErrorListener);
largeMessagesFactory = new JDBCSequentialFileFactory(dbConf.getJdbcConnectionUrl(), driverClassName, JDBCUtils.getSQLProvider(driverClassName, dbConf.getLargeMessageTableName(), SQLProvider.DatabaseStoreType.LARGE_MESSAGE), executor, criticalErrorListener);
}
final int networkTimeout = dbConf.getJdbcNetworkTimeout();
if (networkTimeout >= 0) {
bindingsJournal.setNetworkTimeout(executorFactory.getExecutor(), networkTimeout);
}
if (networkTimeout >= 0) {
messageJournal.setNetworkTimeout(executorFactory.getExecutor(), networkTimeout);
}
if (networkTimeout >= 0) {
largeMessagesFactory.setNetworkTimeout(executorFactory.getExecutor(), networkTimeout);
}
this.bindingsJournal = bindingsJournal;
this.messageJournal = messageJournal;
this.largeMessagesFactory = largeMessagesFactory;
largeMessagesFactory.start();
} catch (Exception e) {
criticalErrorListener.onIOException(e, e.getMessage(), null);

View File

@ -1707,6 +1707,13 @@
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="jdbc-network-timeout" type="xsd:int" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
The JDBC network connection timeout in milliseconds.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:all>
</xsd:complexType>

View File

@ -298,9 +298,9 @@ The message journal is configured using the following attributes in
data files on the journal
The default for this parameter is `30`
- `journal-datasync` (default: true)
This will disable the use of fdatasync on journal writes.
### An important note on disabling disk write cache.
@ -424,6 +424,10 @@ To configure Apache ActiveMQ Artemis to use a database for persisting messages a
The fully qualified class name of the desired database Driver.
- `jdbc-network-timeout`
The JDBC network connection timeout in milliseconds. The default value
is 20000 milliseconds (ie 20 seconds).
## Configuring Apache ActiveMQ Artemis for Zero Persistence