diff --git a/client/conf/db.properties.in b/client/conf/db.properties.in index 8f31aff17e6..0f7d2706a42 100644 --- a/client/conf/db.properties.in +++ b/client/conf/db.properties.in @@ -34,10 +34,14 @@ db.cloud.uri= # CloudStack database tuning parameters +db.cloud.connectionPoolLib=hikaricp db.cloud.maxActive=250 db.cloud.maxIdle=30 -db.cloud.maxWait=10000 -db.cloud.validationQuery=SELECT 1 +db.cloud.maxWait=600000 +db.cloud.minIdleConnections=5 +db.cloud.connectionTimeout=30000 +db.cloud.keepAliveTime=600000 +db.cloud.validationQuery=/* ping */ SELECT 1 db.cloud.testOnBorrow=true db.cloud.testWhileIdle=true db.cloud.timeBetweenEvictionRunsMillis=40000 @@ -70,9 +74,13 @@ db.usage.uri= # usage database tuning parameters +db.usage.connectionPoolLib=hikaricp db.usage.maxActive=100 db.usage.maxIdle=30 -db.usage.maxWait=10000 +db.usage.maxWait=600000 +db.usage.minIdleConnections=5 +db.usage.connectionTimeout=30000 +db.usage.keepAliveTime=600000 db.usage.url.params=serverTimezone=UTC # Simulator database settings @@ -82,9 +90,13 @@ db.simulator.host=@DBHOST@ db.simulator.driver=@DBDRIVER@ db.simulator.port=3306 db.simulator.name=simulator +db.simulator.connectionPoolLib=hikaricp db.simulator.maxActive=250 db.simulator.maxIdle=30 -db.simulator.maxWait=10000 +db.simulator.maxWait=600000 +db.simulator.minIdleConnections=5 +db.simulator.connectionTimeout=30000 +db.simulator.keepAliveTime=600000 db.simulator.autoReconnect=true # Connection URI to the database "simulator". When this property is set, only the following properties will be used along with it: db.simulator.host, db.simulator.port, db.simulator.name, db.simulator.autoReconnect. Other properties will be ignored. diff --git a/developer/pom.xml b/developer/pom.xml index 6cbf483faac..b44446ec0a5 100644 --- a/developer/pom.xml +++ b/developer/pom.xml @@ -42,6 +42,10 @@ org.apache.commons commons-pool2 + + com.zaxxer + HikariCP + org.jasypt jasypt diff --git a/engine/schema/src/main/java/com/cloud/upgrade/DatabaseCreator.java b/engine/schema/src/main/java/com/cloud/upgrade/DatabaseCreator.java index 154a8d11887..384826227af 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/DatabaseCreator.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/DatabaseCreator.java @@ -116,10 +116,6 @@ public class DatabaseCreator { } public static void main(String[] args) { - - ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] {"/com/cloud/upgrade/databaseCreatorContext.xml"}); - appContext.getBean(ComponentContext.class); - String dbPropsFile = ""; List sqlFiles = new ArrayList(); List upgradeClasses = new ArrayList(); @@ -166,13 +162,17 @@ public class DatabaseCreator { System.exit(1); } + initDB(dbPropsFile, rootPassword, databases, dryRun); + + ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] {"/com/cloud/upgrade/databaseCreatorContext.xml"}); + appContext.getBean(ComponentContext.class); + try { TransactionLegacy.initDataSource(dbPropsFile); } catch (IOException e) { e.printStackTrace(); System.exit(1); } - initDB(dbPropsFile, rootPassword, databases, dryRun); // Process sql files for (String sqlFile : sqlFiles) { diff --git a/engine/storage/snapshot/pom.xml b/engine/storage/snapshot/pom.xml index ac0daeabf76..f29b43d8de0 100644 --- a/engine/storage/snapshot/pom.xml +++ b/engine/storage/snapshot/pom.xml @@ -56,6 +56,11 @@ ${project.version} compile + + mysql + mysql-connector-java + test + diff --git a/framework/db/pom.xml b/framework/db/pom.xml index d4d3b6b8772..586d72f34f3 100644 --- a/framework/db/pom.xml +++ b/framework/db/pom.xml @@ -40,6 +40,10 @@ org.apache.commons commons-dbcp2 + + com.zaxxer + HikariCP + commons-io commons-io @@ -48,6 +52,10 @@ org.apache.commons commons-pool2 + + mysql + mysql-connector-java + org.apache.cloudstack cloud-utils diff --git a/framework/db/src/main/java/com/cloud/utils/db/ConnectionConcierge.java b/framework/db/src/main/java/com/cloud/utils/db/ConnectionConcierge.java index 7cf34e6955c..c7c869ba920 100644 --- a/framework/db/src/main/java/com/cloud/utils/db/ConnectionConcierge.java +++ b/framework/db/src/main/java/com/cloud/utils/db/ConnectionConcierge.java @@ -145,7 +145,7 @@ public class ConnectionConcierge { protected String testValidity(String name, Connection conn) { if (conn != null) { synchronized (conn) { - try (PreparedStatement pstmt = conn.prepareStatement("SELECT 1");) { + try (PreparedStatement pstmt = conn.prepareStatement("/* ping */ SELECT 1");) { pstmt.executeQuery(); } catch (Throwable th) { logger.error("Unable to keep the db connection for " + name, th); diff --git a/framework/db/src/main/java/com/cloud/utils/db/TransactionLegacy.java b/framework/db/src/main/java/com/cloud/utils/db/TransactionLegacy.java index 00fa8e4c0d5..88af397c06a 100644 --- a/framework/db/src/main/java/com/cloud/utils/db/TransactionLegacy.java +++ b/framework/db/src/main/java/com/cloud/utils/db/TransactionLegacy.java @@ -38,17 +38,20 @@ import org.apache.commons.dbcp2.DriverManagerConnectionFactory; import org.apache.commons.dbcp2.PoolableConnection; import org.apache.commons.dbcp2.PoolableConnectionFactory; import org.apache.commons.dbcp2.PoolingDataSource; +import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.pool2.ObjectPool; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; -import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import com.cloud.utils.Pair; import com.cloud.utils.PropertiesUtil; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.mgmt.JmxUtil; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; /** * Transaction abstracts away the Connection object in JDBC. It allows the @@ -95,6 +98,8 @@ public class TransactionLegacy implements Closeable { } } + private static final String CONNECTION_POOL_LIB_DBCP = "dbcp"; + private final LinkedList _stack; private long _id; @@ -1020,6 +1025,21 @@ public class TransactionLegacy implements Closeable { } } + private static T parseNumber(String value, Class type) { + if (value == null) { + return null; + } + try { + if (type.equals(Long.class)) { + return type.cast(Long.parseLong(value)); + } else { + return type.cast(Integer.parseInt(value)); + } + } catch (NumberFormatException ignored) { + return null; + } + } + @SuppressWarnings({"rawtypes", "unchecked"}) public static void initDataSource(Properties dbProps) { try { @@ -1030,9 +1050,12 @@ public class TransactionLegacy implements Closeable { LOGGER.info("Is Data Base High Availiability enabled? Ans : " + s_dbHAEnabled); String loadBalanceStrategy = dbProps.getProperty("db.ha.loadBalanceStrategy"); // FIXME: If params are missing...default them???? - final int cloudMaxActive = Integer.parseInt(dbProps.getProperty("db.cloud.maxActive")); - final int cloudMaxIdle = Integer.parseInt(dbProps.getProperty("db.cloud.maxIdle")); - final long cloudMaxWait = Long.parseLong(dbProps.getProperty("db.cloud.maxWait")); + final Integer cloudMaxActive = parseNumber(dbProps.getProperty("db.cloud.maxActive"), Integer.class); + final Integer cloudMaxIdle = parseNumber(dbProps.getProperty("db.cloud.maxIdle"), Integer.class); + final Long cloudMaxWait = parseNumber(dbProps.getProperty("db.cloud.maxWait"), Long.class); + final Integer cloudMinIdleConnections = parseNumber(dbProps.getProperty("db.cloud.minIdleConnections"), Integer.class); + final Long cloudConnectionTimeout = parseNumber(dbProps.getProperty("db.cloud.connectionTimeout"), Long.class); + final Long cloudKeepAliveTimeout = parseNumber(dbProps.getProperty("db.cloud.keepAliveTime"), Long.class); final String cloudUsername = dbProps.getProperty("db.cloud.username"); final String cloudPassword = dbProps.getProperty("db.cloud.password"); final String cloudValidationQuery = dbProps.getProperty("db.cloud.validationQuery"); @@ -1071,14 +1094,19 @@ public class TransactionLegacy implements Closeable { DriverLoader.loadDriver(cloudUriAndDriver.second()); // Default Data Source for CloudStack - s_ds = createDataSource(cloudUriAndDriver.first(), cloudUsername, cloudPassword, cloudMaxActive, cloudMaxIdle, cloudMaxWait, - cloudTimeBtwEvictionRunsMillis, cloudMinEvcitableIdleTimeMillis, cloudTestWhileIdle, cloudTestOnBorrow, - cloudValidationQuery, isolationLevel); + s_ds = createDataSource(dbProps.getProperty("db.cloud.connectionPoolLib"), cloudUriAndDriver.first(), + cloudUsername, cloudPassword, cloudMaxActive, cloudMaxIdle, cloudMaxWait, + cloudTimeBtwEvictionRunsMillis, cloudMinEvcitableIdleTimeMillis, cloudTestWhileIdle, + cloudTestOnBorrow, cloudValidationQuery, cloudMinIdleConnections, cloudConnectionTimeout, + cloudKeepAliveTimeout, isolationLevel, "cloud"); // Configure the usage db - final int usageMaxActive = Integer.parseInt(dbProps.getProperty("db.usage.maxActive")); - final int usageMaxIdle = Integer.parseInt(dbProps.getProperty("db.usage.maxIdle")); - final long usageMaxWait = Long.parseLong(dbProps.getProperty("db.usage.maxWait")); + final Integer usageMaxActive = parseNumber(dbProps.getProperty("db.usage.maxActive"), Integer.class); + final Integer usageMaxIdle = parseNumber(dbProps.getProperty("db.usage.maxIdle"), Integer.class); + final Long usageMaxWait = parseNumber(dbProps.getProperty("db.usage.maxWait"), Long.class); + final Integer usageMinIdleConnections = parseNumber(dbProps.getProperty("db.usage.minIdleConnections"), Integer.class); + final Long usageConnectionTimeout = parseNumber(dbProps.getProperty("db.usage.connectionTimeout"), Long.class); + final Long usageKeepAliveTimeout = parseNumber(dbProps.getProperty("db.usage.keepAliveTime"), Long.class); final String usageUsername = dbProps.getProperty("db.usage.username"); final String usagePassword = dbProps.getProperty("db.usage.password"); @@ -1087,15 +1115,19 @@ public class TransactionLegacy implements Closeable { DriverLoader.loadDriver(usageUriAndDriver.second()); // Data Source for usage server - s_usageDS = createDataSource(usageUriAndDriver.first(), usageUsername, usagePassword, - usageMaxActive, usageMaxIdle, usageMaxWait, null, null, null, null, - null, isolationLevel); + s_usageDS = createDataSource(dbProps.getProperty("db.usage.connectionPoolLib"), usageUriAndDriver.first(), + usageUsername, usagePassword, usageMaxActive, usageMaxIdle, usageMaxWait, null, + null, null, null, null, + usageMinIdleConnections, usageConnectionTimeout, usageKeepAliveTimeout, isolationLevel, "usage"); try { // Configure the simulator db - final int simulatorMaxActive = Integer.parseInt(dbProps.getProperty("db.simulator.maxActive")); - final int simulatorMaxIdle = Integer.parseInt(dbProps.getProperty("db.simulator.maxIdle")); - final long simulatorMaxWait = Long.parseLong(dbProps.getProperty("db.simulator.maxWait")); + final Integer simulatorMaxActive = parseNumber(dbProps.getProperty("db.simulator.maxActive"), Integer.class); + final Integer simulatorMaxIdle = parseNumber(dbProps.getProperty("db.simulator.maxIdle"), Integer.class); + final Long simulatorMaxWait = parseNumber(dbProps.getProperty("db.simulator.maxWait"), Long.class); + final Integer simulatorMinIdleConnections = parseNumber(dbProps.getProperty("db.simulator.minIdleConnections"), Integer.class); + final Long simulatorConnectionTimeout = parseNumber(dbProps.getProperty("db.simulator.connectionTimeout"), Long.class); + final Long simulatorKeepAliveTimeout = parseNumber(dbProps.getProperty("db.simulator.keepAliveTime"), Long.class); final String simulatorUsername = dbProps.getProperty("db.simulator.username"); final String simulatorPassword = dbProps.getProperty("db.simulator.password"); @@ -1122,15 +1154,18 @@ public class TransactionLegacy implements Closeable { DriverLoader.loadDriver(simulatorDriver); - s_simulatorDS = createDataSource(simulatorConnectionUri, simulatorUsername, simulatorPassword, - simulatorMaxActive, simulatorMaxIdle, simulatorMaxWait, null, null, null, null, cloudValidationQuery, isolationLevel); + s_simulatorDS = createDataSource(dbProps.getProperty("db.simulator.connectionPoolLib"), + simulatorConnectionUri, simulatorUsername, simulatorPassword, simulatorMaxActive, + simulatorMaxIdle, simulatorMaxWait, null, null, null, null, + cloudValidationQuery, simulatorMinIdleConnections, simulatorConnectionTimeout, + simulatorKeepAliveTimeout, isolationLevel, "simulator"); } catch (Exception e) { LOGGER.debug("Simulator DB properties are not available. Not initializing simulator DS"); } } catch (final Exception e) { - s_ds = getDefaultDataSource("cloud"); - s_usageDS = getDefaultDataSource("cloud_usage"); - s_simulatorDS = getDefaultDataSource("cloud_simulator"); + s_ds = getDefaultDataSource(dbProps.getProperty("db.cloud.connectionPoolLib"), "cloud"); + s_usageDS = getDefaultDataSource(dbProps.getProperty("db.usage.connectionPoolLib"), "cloud_usage"); + s_simulatorDS = getDefaultDataSource(dbProps.getProperty("db.simulator.connectionPoolLib"), "simulator"); LOGGER.warn( "Unable to load db configuration, using defaults with 5 connections. Falling back on assumed datasource on localhost:3306 using username:password=cloud:cloud. Please check your configuration", e); @@ -1222,11 +1257,71 @@ public class TransactionLegacy implements Closeable { /** * Creates a data source */ - private static DataSource createDataSource(String uri, String username, String password, + private static DataSource createDataSource(String connectionPoolLib, String uri, String username, String password, + Integer maxActive, Integer maxIdle, Long maxWait, Long timeBtwnEvictionRuns, Long minEvictableIdleTime, + Boolean testWhileIdle, Boolean testOnBorrow, String validationQuery, Integer minIdleConnections, + Long connectionTimeout, Long keepAliveTime, Integer isolationLevel, String dsName) { + LOGGER.debug("Creating datasource for database: {} with connection pool lib: {}", dsName, + connectionPoolLib); + if (CONNECTION_POOL_LIB_DBCP.equals(connectionPoolLib)) { + return createDbcpDataSource(uri, username, password, maxActive, maxIdle, maxWait, timeBtwnEvictionRuns, + minEvictableIdleTime, testWhileIdle, testOnBorrow, validationQuery, isolationLevel); + } + return createHikaricpDataSource(uri, username, password, maxActive, maxIdle, maxWait, minIdleConnections, + connectionTimeout, keepAliveTime, isolationLevel, dsName); + } + + private static DataSource createHikaricpDataSource(String uri, String username, String password, Integer maxActive, Integer maxIdle, Long maxWait, - Long timeBtwnEvictionRuns, Long minEvictableIdleTime, - Boolean testWhileIdle, Boolean testOnBorrow, - String validationQuery, Integer isolationLevel) { + Integer minIdleConnections, Long connectionTimeout, Long keepAliveTime, + Integer isolationLevel, String dsName) { + HikariConfig config = new HikariConfig(); + config.setJdbcUrl(uri); + config.setUsername(username); + config.setPassword(password); + + config.setPoolName(dsName); + + // Connection pool properties + config.setMaximumPoolSize(ObjectUtils.defaultIfNull(maxActive, 250)); + config.setIdleTimeout(ObjectUtils.defaultIfNull(maxIdle, 30) * 1000); + config.setMaxLifetime(ObjectUtils.defaultIfNull(maxWait, 600000L)); + config.setMinimumIdle(ObjectUtils.defaultIfNull(minIdleConnections, 5)); + config.setConnectionTimeout(ObjectUtils.defaultIfNull(connectionTimeout, 30000L)); + config.setKeepaliveTime(ObjectUtils.defaultIfNull(keepAliveTime, 600000L)); + + String isolationLevelString = "TRANSACTION_READ_COMMITTED"; + if (isolationLevel == Connection.TRANSACTION_SERIALIZABLE) { + isolationLevelString = "TRANSACTION_SERIALIZABLE"; + } else if (isolationLevel == Connection.TRANSACTION_READ_UNCOMMITTED) { + isolationLevelString = "TRANSACTION_READ_UNCOMMITTED"; + } else if (isolationLevel == Connection.TRANSACTION_REPEATABLE_READ) { + isolationLevelString = "TRANSACTION_REPEATABLE_READ"; + } + config.setTransactionIsolation(isolationLevelString); + + // Standard datasource config for MySQL + config.addDataSourceProperty("cachePrepStmts", "true"); + config.addDataSourceProperty("prepStmtCacheSize", "250"); + config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); + // Additional config for MySQL + config.addDataSourceProperty("useServerPrepStmts", "true"); + config.addDataSourceProperty("useLocalSessionState", "true"); + config.addDataSourceProperty("rewriteBatchedStatements", "true"); + config.addDataSourceProperty("cacheResultSetMetadata", "true"); + config.addDataSourceProperty("cacheServerConfiguration", "true"); + config.addDataSourceProperty("elideSetAutoCommits", "true"); + config.addDataSourceProperty("maintainTimeStats", "false"); + + HikariDataSource dataSource = new HikariDataSource(config); + return dataSource; + } + + private static DataSource createDbcpDataSource(String uri, String username, String password, + Integer maxActive, Integer maxIdle, Long maxWait, + Long timeBtwnEvictionRuns, Long minEvictableIdleTime, + Boolean testWhileIdle, Boolean testOnBorrow, + String validationQuery, Integer isolationLevel) { ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(uri, username, password); PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory, null); GenericObjectPoolConfig config = createPoolConfig(maxActive, maxIdle, maxWait, timeBtwnEvictionRuns, minEvictableIdleTime, testWhileIdle, testOnBorrow); @@ -1267,6 +1362,44 @@ public class TransactionLegacy implements Closeable { return config; } + private static DataSource getDefaultDataSource(final String connectionPoolLib, final String database) { + LOGGER.debug("Creating default datasource for database: {} with connection pool lib: {}", + database, connectionPoolLib); + if (CONNECTION_POOL_LIB_DBCP.equalsIgnoreCase(connectionPoolLib)) { + return getDefaultDbcpDataSource(database); + } + return getDefaultHikaricpDataSource(database); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private static DataSource getDefaultHikaricpDataSource(final String database) { + HikariConfig config = new HikariConfig(); + config.setJdbcUrl("jdbc:mysql://localhost:3306/" + database + "?" + CONNECTION_PARAMS); + config.setUsername("cloud"); + config.setPassword("cloud"); + config.setPoolName(database); + config.setDriverClassName("com.mysql.cj.jdbc.Driver"); + config.setMaximumPoolSize(250); + config.setConnectionTimeout(1000); + config.setIdleTimeout(1000); + config.setKeepaliveTime(1000); + config.setMaxLifetime(1000); + config.setTransactionIsolation("TRANSACTION_READ_COMMITTED"); + config.setInitializationFailTimeout(-1L); + config.addDataSourceProperty("cachePrepStmts", "true"); + config.addDataSourceProperty("prepStmtCacheSize", "250"); + config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); + return new HikariDataSource(config); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private static DataSource getDefaultDbcpDataSource(final String database) { + final ConnectionFactory connectionFactory = new DriverManagerConnectionFactory("jdbc:mysql://localhost:3306/" + database + "?" + CONNECTION_PARAMS, "cloud", "cloud"); + final PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory, null); + final GenericObjectPool connectionPool = new GenericObjectPool(poolableConnectionFactory); + return new PoolingDataSource(connectionPool); + } + private static String getDBHAParams(String dbName, Properties dbProps) { StringBuilder sb = new StringBuilder(); sb.append("failOverReadOnly=" + dbProps.getProperty("db." + dbName + ".failOverReadOnly")); @@ -1278,14 +1411,6 @@ public class TransactionLegacy implements Closeable { return sb.toString(); } - @SuppressWarnings({"unchecked", "rawtypes"}) - private static DataSource getDefaultDataSource(final String database) { - final ConnectionFactory connectionFactory = new DriverManagerConnectionFactory("jdbc:mysql://localhost:3306/" + database + "?" + CONNECTION_PARAMS, "cloud", "cloud"); - final PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory, null); - final GenericObjectPool connectionPool = new GenericObjectPool(poolableConnectionFactory); - return new PoolingDataSource(connectionPool); - } - /** * Used for unit testing primarily * diff --git a/plugins/network-elements/globodns/pom.xml b/plugins/network-elements/globodns/pom.xml index e27a4a54d16..c0200921f20 100644 --- a/plugins/network-elements/globodns/pom.xml +++ b/plugins/network-elements/globodns/pom.xml @@ -32,5 +32,10 @@ com.globo.globodns globodns-client + + mysql + mysql-connector-java + test + diff --git a/plugins/network-elements/tungsten/pom.xml b/plugins/network-elements/tungsten/pom.xml index b0a46b1331a..1345268d313 100644 --- a/plugins/network-elements/tungsten/pom.xml +++ b/plugins/network-elements/tungsten/pom.xml @@ -47,5 +47,10 @@ ch.qos.reload4j reload4j + + mysql + mysql-connector-java + test + diff --git a/pom.xml b/pom.xml index 2ed3f8301cc..1acea98096f 100644 --- a/pom.xml +++ b/pom.xml @@ -102,6 +102,7 @@ 1.10 1.3.3 2.9.0 + 5.1.0 0.5 2.6 2.9.0 @@ -364,6 +365,7 @@ commons-daemon ${cs.daemon.version} + org.apache.commons commons-dbcp2 @@ -375,6 +377,11 @@ + + com.zaxxer + HikariCP + ${cs.hikaricp.version} + commons-discovery commons-discovery @@ -455,6 +462,12 @@ reload4j ${cs.reload4j.version} + + mysql + mysql-connector-java + ${cs.mysql.version} + test + log4j apache-log4j-extras diff --git a/server/pom.xml b/server/pom.xml index 269583c381a..ec157b00e30 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -164,6 +164,11 @@ cloud-framework-agent-lb ${project.version} + + org.apache.cloudstack + cloud-framework-db + ${project.version} + org.apache.cloudstack cloud-engine-storage-configdrive diff --git a/usage/conf/db.properties.in b/usage/conf/db.properties.in index 35a40def7b1..c597bb9fad3 100644 --- a/usage/conf/db.properties.in +++ b/usage/conf/db.properties.in @@ -24,7 +24,11 @@ db.usage.port=3306 db.usage.name=cloud_usage # usage database tuning parameters +db.usage.connectionPoolLib=hikaricp db.usage.maxActive=100 db.usage.maxIdle=30 db.usage.maxWait=10000 +db.usage.minIdleConnections=5 +db.usage.connectionTimeout=30000 +db.usage.keepAliveTime=600000 db.usage.autoReconnect=true