mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
support maxEvictableIdleTimeMillis
This commit is contained in:
@@ -97,7 +97,8 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
|
||||
* @see #setMinEvictableIdleTimeMillis
|
||||
*/
|
||||
public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L;
|
||||
public static final long DEFAULT_PHY_TIMEOUT_MILLIS = 1000L * 60L * 60L * 7;
|
||||
public static final long DEFAULT_MAX_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 60L * 7;
|
||||
public static final long DEFAULT_PHY_TIMEOUT_MILLIS = -1;
|
||||
|
||||
protected volatile boolean defaultAutoCommit = true;
|
||||
protected volatile Boolean defaultReadOnly;
|
||||
@@ -159,6 +160,7 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
|
||||
protected volatile int numTestsPerEvictionRun = DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
|
||||
|
||||
protected volatile long minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
|
||||
protected volatile long maxEvictableIdleTimeMillis = DEFAULT_MAX_EVICTABLE_IDLE_TIME_MILLIS;
|
||||
|
||||
protected volatile long phyTimeoutMillis = DEFAULT_PHY_TIMEOUT_MILLIS;
|
||||
|
||||
@@ -692,8 +694,26 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
|
||||
if (minEvictableIdleTimeMillis < 1000 * 30) {
|
||||
LOG.error("minEvictableIdleTimeMillis should be greater than 30000");
|
||||
}
|
||||
|
||||
this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
|
||||
}
|
||||
|
||||
public long getMaxEvictableIdleTimeMillis() {
|
||||
return maxEvictableIdleTimeMillis;
|
||||
}
|
||||
|
||||
|
||||
public void setMaxEvictableIdleTimeMillis(long maxEvictableIdleTimeMillis) {
|
||||
if (maxEvictableIdleTimeMillis < 1000 * 30) {
|
||||
LOG.error("maxEvictableIdleTimeMillis should be greater than 30000");
|
||||
}
|
||||
|
||||
if (maxEvictableIdleTimeMillis < minEvictableIdleTimeMillis) {
|
||||
throw new IllegalArgumentException("maxEvictableIdleTimeMillis must be grater than minEvictableIdleTimeMillis");
|
||||
}
|
||||
|
||||
this.maxEvictableIdleTimeMillis = maxEvictableIdleTimeMillis;
|
||||
}
|
||||
|
||||
public long getPhyTimeoutMillis() {
|
||||
return phyTimeoutMillis;
|
||||
|
||||
@@ -53,6 +53,8 @@ import javax.sql.ConnectionEventListener;
|
||||
import javax.sql.ConnectionPoolDataSource;
|
||||
import javax.sql.PooledConnection;
|
||||
|
||||
import org.apache.ibatis.jdbc.SQL;
|
||||
|
||||
import com.alibaba.druid.Constants;
|
||||
import com.alibaba.druid.TransactionTimeoutException;
|
||||
import com.alibaba.druid.VERSION;
|
||||
@@ -283,6 +285,39 @@ public class DruidDataSource extends DruidAbstractDataSource
|
||||
this.setFailFast(value);
|
||||
}
|
||||
}
|
||||
{
|
||||
String property = properties.getProperty("druid.phyTimeoutMillis");
|
||||
if (property != null && property.length() > 0) {
|
||||
try {
|
||||
long value = Long.parseLong(property);
|
||||
this.setPhyTimeoutMillis(value);
|
||||
} catch (NumberFormatException e) {
|
||||
LOG.error("illegal property 'druid.phyTimeoutMillis'", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
String property = properties.getProperty("druid.minEvictableIdleTimeMillis");
|
||||
if (property != null && property.length() > 0) {
|
||||
try {
|
||||
long value = Long.parseLong(property);
|
||||
this.setMinEvictableIdleTimeMillis(value);
|
||||
} catch (NumberFormatException e) {
|
||||
LOG.error("illegal property 'druid.minEvictableIdleTimeMillis'", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
String property = properties.getProperty("druid.maxEvictableIdleTimeMillis");
|
||||
if (property != null && property.length() > 0) {
|
||||
try {
|
||||
long value = Long.parseLong(property);
|
||||
this.setMaxEvictableIdleTimeMillis(value);
|
||||
} catch (NumberFormatException e) {
|
||||
LOG.error("illegal property 'druid.maxEvictableIdleTimeMillis'", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isUseGlobalDataSourceStat() {
|
||||
@@ -541,8 +576,6 @@ public class DruidDataSource extends DruidAbstractDataSource
|
||||
return;
|
||||
}
|
||||
|
||||
init = true;
|
||||
|
||||
initStackTrace = Utils.toString(Thread.currentThread().getStackTrace());
|
||||
|
||||
this.id = DruidDriver.createDataSourceId();
|
||||
@@ -589,13 +622,16 @@ public class DruidDataSource extends DruidAbstractDataSource
|
||||
}
|
||||
|
||||
if (getInitialSize() > maxActive) {
|
||||
throw new IllegalArgumentException("illegal initialSize " + this.initialSize + ", maxActieve "
|
||||
+ maxActive);
|
||||
throw new IllegalArgumentException("illegal initialSize " + this.initialSize + ", maxActieve " + maxActive);
|
||||
}
|
||||
|
||||
if (timeBetweenLogStatsMillis > 0 && useGlobalDataSourceStat) {
|
||||
throw new IllegalArgumentException("timeBetweenLogStatsMillis not support useGlobalDataSourceStat=true");
|
||||
}
|
||||
|
||||
if (maxEvictableIdleTimeMillis < minEvictableIdleTimeMillis) {
|
||||
throw new SQLException("maxEvictableIdleTimeMillis must be grater than minEvictableIdleTimeMillis");
|
||||
}
|
||||
|
||||
if (this.driverClass != null) {
|
||||
this.driverClass = driverClass.trim();
|
||||
@@ -666,6 +702,7 @@ public class DruidDataSource extends DruidAbstractDataSource
|
||||
createAndStartDestroyThread();
|
||||
|
||||
initedLatch.await();
|
||||
init = true;
|
||||
|
||||
initedTime = new Date();
|
||||
registerMbean();
|
||||
@@ -674,7 +711,7 @@ public class DruidDataSource extends DruidAbstractDataSource
|
||||
throw connectError;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
LOG.error("dataSource init error", e);
|
||||
LOG.error("{dataSource-" + this.getID() + "} init error", e);
|
||||
throw e;
|
||||
} catch (InterruptedException e) {
|
||||
throw new SQLException(e.getMessage(), e);
|
||||
@@ -2185,24 +2222,33 @@ public class DruidDataSource extends DruidAbstractDataSource
|
||||
try {
|
||||
final int checkCount = poolingCount - minIdle;
|
||||
final long currentTimeMillis = System.currentTimeMillis();
|
||||
for (int i = 0; i < checkCount; ++i) {
|
||||
for (int i = 0; i < poolingCount; ++i) {
|
||||
DruidConnectionHolder connection = connections[i];
|
||||
|
||||
long phyConnectTimeMillis = connection.getTimeMillis() - currentTimeMillis;//physical connection connected time
|
||||
if( phyConnectTimeMillis > phyTimeoutMillis ){
|
||||
evictList.add(connection);//if physical connection connected greater than phyTimeoutMillis, close the connection, for mysql 8 hours timeout
|
||||
continue;
|
||||
}
|
||||
|
||||
if (checkTime) {
|
||||
long phyConnectTimeMillis = connection.getTimeMillis() - currentTimeMillis;//physical connection connected time
|
||||
if (phyTimeoutMillis > 0 && phyConnectTimeMillis > phyTimeoutMillis) {
|
||||
evictList.add(connection);
|
||||
continue;
|
||||
}
|
||||
|
||||
long idleMillis = currentTimeMillis - connection.getLastActiveTimeMillis();
|
||||
if (idleMillis >= minEvictableIdleTimeMillis) {
|
||||
|
||||
if (idleMillis < minEvictableIdleTimeMillis) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (checkTime && i < checkCount) {
|
||||
evictList.add(connection);
|
||||
} else if (idleMillis > maxEvictableIdleTimeMillis) {
|
||||
evictList.add(connection);
|
||||
}
|
||||
} else {
|
||||
if (i < checkCount) {
|
||||
evictList.add(connection);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
evictList.add(connection);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.alibaba.druid.bvt.pool.basic;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import com.alibaba.druid.pool.GetConnectionTimeoutException;
|
||||
import com.alibaba.druid.util.JdbcUtils;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class MaxEvictableIdleTimeMillisTest extends TestCase {
|
||||
|
||||
private DruidDataSource dataSource;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
dataSource = new DruidDataSource();
|
||||
dataSource.setUrl("jdbc:mock:xxx");
|
||||
dataSource.setTestOnBorrow(false);
|
||||
dataSource.setMaxActive(50);
|
||||
dataSource.setMinIdle(5);
|
||||
dataSource.setMinEvictableIdleTimeMillis(10);
|
||||
dataSource.setMaxEvictableIdleTimeMillis(100);
|
||||
dataSource.setMaxWait(20);
|
||||
dataSource.init();
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
dataSource.close();
|
||||
}
|
||||
|
||||
public void test_error() throws Exception {
|
||||
Exception error = null;
|
||||
try {
|
||||
dataSource.setMaxEvictableIdleTimeMillis(1);
|
||||
} catch (Exception ex) {
|
||||
error = ex;
|
||||
}
|
||||
Assert.assertNotNull(error);
|
||||
Assert.assertEquals(100, dataSource.getMaxEvictableIdleTimeMillis());
|
||||
}
|
||||
|
||||
public void test_error2() throws Exception {
|
||||
Exception error = null;
|
||||
try {
|
||||
dataSource.setMaxEvictableIdleTimeMillis(1);
|
||||
} catch (Exception ex) {
|
||||
error = ex;
|
||||
}
|
||||
Assert.assertNotNull(error);
|
||||
Assert.assertEquals(100, dataSource.getMaxEvictableIdleTimeMillis());
|
||||
}
|
||||
|
||||
public void test_max() throws Exception {
|
||||
connect(10);
|
||||
|
||||
Assert.assertEquals(10, dataSource.getPoolingCount());
|
||||
Thread.sleep(20);
|
||||
dataSource.shrink(true);
|
||||
Assert.assertEquals(5, dataSource.getPoolingCount());
|
||||
|
||||
Thread.sleep(100);
|
||||
dataSource.shrink(true);
|
||||
Assert.assertEquals(0, dataSource.getPoolingCount());
|
||||
}
|
||||
|
||||
public int connect(int count) throws Exception {
|
||||
int successCount = 0;
|
||||
Connection[] connections = new Connection[count];
|
||||
for (int i = 0; i < count; ++i) {
|
||||
try {
|
||||
connections[i] = dataSource.getConnection();
|
||||
successCount++;
|
||||
} catch (GetConnectionTimeoutException e) {
|
||||
// skip
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
JdbcUtils.close(connections[i]);
|
||||
}
|
||||
|
||||
return successCount;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.alibaba.druid.bvt.pool.basic;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import com.alibaba.druid.pool.GetConnectionTimeoutException;
|
||||
import com.alibaba.druid.util.JdbcUtils;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class MaxEvictableIdleTimeMillisTest2 extends TestCase {
|
||||
|
||||
private DruidDataSource dataSource;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
dataSource = new DruidDataSource();
|
||||
dataSource.setUrl("jdbc:mock:xxx");
|
||||
dataSource.setTestOnBorrow(false);
|
||||
dataSource.setMaxActive(50);
|
||||
dataSource.setMinIdle(5);
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
dataSource.close();
|
||||
}
|
||||
|
||||
public void test_error() throws Exception {
|
||||
Exception error = null;
|
||||
try {
|
||||
dataSource.setMinEvictableIdleTimeMillis(20);
|
||||
dataSource.setMaxEvictableIdleTimeMillis(30);
|
||||
dataSource.setMinEvictableIdleTimeMillis(100);
|
||||
dataSource.setMaxWait(20);
|
||||
dataSource.init();
|
||||
} catch (Exception ex) {
|
||||
error = ex;
|
||||
ex.printStackTrace();
|
||||
}
|
||||
Assert.assertNotNull(error);
|
||||
Assert.assertTrue(dataSource.isInited());
|
||||
Assert.assertEquals(30, dataSource.getMaxEvictableIdleTimeMillis());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -33,7 +33,7 @@ public class MaxActiveChangeTest extends TestCase {
|
||||
dataSource.setUrl("jdbc:mock:xxx");
|
||||
dataSource.setTestOnBorrow(false);
|
||||
dataSource.setMaxActive(3);
|
||||
dataSource.setMinIdle(1);
|
||||
dataSource.setMinIdle(2);
|
||||
dataSource.setMinEvictableIdleTimeMillis(1000 * 60 * 5);
|
||||
dataSource.setMaxWait(20);
|
||||
dataSource.init();
|
||||
@@ -61,44 +61,45 @@ public class MaxActiveChangeTest extends TestCase {
|
||||
Assert.assertEquals(3, dataSource.getPoolingCount());
|
||||
}
|
||||
|
||||
dataSource.setMaxActive(4);
|
||||
dataSource.setMaxActive(5);
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
Assert.assertEquals(4, connect(4));
|
||||
Assert.assertEquals(4, dataSource.getPoolingCount());
|
||||
Assert.assertEquals(5, connect(5));
|
||||
Assert.assertEquals(5, dataSource.getPoolingCount());
|
||||
}
|
||||
|
||||
dataSource.shrink();
|
||||
Assert.assertEquals(1, dataSource.getPoolingCount());
|
||||
Assert.assertEquals(2, dataSource.getPoolingCount());
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
Assert.assertEquals(4, connect(4));
|
||||
Assert.assertEquals(4, dataSource.getPoolingCount());
|
||||
Assert.assertEquals(5, connect(5));
|
||||
Assert.assertEquals(5, dataSource.getPoolingCount());
|
||||
}
|
||||
|
||||
Assert.assertEquals(4, dataSource.getPoolingCount());
|
||||
Assert.assertEquals(5, dataSource.getPoolingCount());
|
||||
dataSource.setMaxActive(3);
|
||||
|
||||
Assert.assertEquals(4, dataSource.getPoolingCount());
|
||||
Assert.assertEquals(5, dataSource.getPoolingCount());
|
||||
|
||||
dataSource.shrink();
|
||||
Assert.assertEquals(1, dataSource.getPoolingCount());
|
||||
Assert.assertEquals(2, dataSource.getPoolingCount());
|
||||
|
||||
// 确保收缩之后不会再长上去
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
Assert.assertEquals(3, connect(4));
|
||||
Assert.assertEquals(3, connect(5));
|
||||
Assert.assertEquals(3, dataSource.getPoolingCount());
|
||||
}
|
||||
|
||||
dataSource.setMaxActive(2);
|
||||
dataSource.shrink();
|
||||
Assert.assertEquals(1, dataSource.getPoolingCount());
|
||||
Assert.assertEquals(2, dataSource.getPoolingCount());
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
Assert.assertEquals(2, connect(3));
|
||||
Assert.assertEquals(2, dataSource.getPoolingCount());
|
||||
}
|
||||
|
||||
dataSource.setMinIdle(1);
|
||||
dataSource.setMaxActive(1);
|
||||
dataSource.shrink();
|
||||
Assert.assertEquals(1, dataSource.getPoolingCount());
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.alibaba.druid.bvt.sql.schemaStat;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.parser.SQLParserUtils;
|
||||
import com.alibaba.druid.sql.parser.SQLStatementParser;
|
||||
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
|
||||
import com.alibaba.druid.util.JdbcConstants;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class SchemaStatTest2 extends TestCase {
|
||||
public void test_schemaStat() throws Exception {
|
||||
String sql = "select "
|
||||
+ " create_time_dd as 来电日期"
|
||||
+ " from alisec_app.adl_tb_wing_rubbish_laidian_new_reason_realname_fdt "
|
||||
+ " order by 来电日期 desc limit 30;";
|
||||
|
||||
|
||||
String dbType = JdbcConstants.MYSQL;
|
||||
SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType);
|
||||
SQLStatement stmt = parser.parseStatementList().get(0);
|
||||
|
||||
SchemaStatVisitor statVisitor = SQLUtils.createSchemaStatVisitor(dbType);
|
||||
stmt.accept(statVisitor);
|
||||
|
||||
System.out.println(statVisitor.getColumns());
|
||||
|
||||
Assert.assertEquals(1, statVisitor.getColumns().size());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user