diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index 5c2b6b5f05..a41f226d4b 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -36,6 +36,7 @@ import java.util.ServiceLoader; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; @@ -117,6 +118,10 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat private long notEmptySignalCount = 0L; private long notEmptyWaitNanos = 0L; + private int keepAliveCheckCount = 0; + private final AtomicInteger keepAliveCheckOkCount = new AtomicInteger(); + private final AtomicInteger keepAliveCheckErrCount = new AtomicInteger(); + private int activePeak = 0; private long activePeakTime = 0; private int poolingPeak = 0; @@ -2123,7 +2128,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat @Override public void run() { - shrink(true); + shrink(true, keepAlive); if (isRemoveAbandoned()) { removeAbandoned(); @@ -2323,9 +2328,11 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat if (checkTime && i < checkCount) { evictConnections[evictCount++] = connection; } else if (idleMillis > maxEvictableIdleTimeMillis) { - evictConnections[evictCount++] = connection; - } else { - keepAliveConnections[keepAliveCount++] = connection; + if (keepAlive) { + keepAliveConnections[keepAliveCount++] = connection; + } else { + evictConnections[evictCount++] = connection; + } } } else { if (i < checkCount) { @@ -2342,6 +2349,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat Arrays.fill(connections, poolingCount - removeCount, poolingCount, null); poolingCount -= removeCount; } + keepAliveCheckCount += keepAliveCount; } finally { lock.unlock(); } @@ -2358,21 +2366,26 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat if (keepAliveCount > 0) { for (int i = 0; i < keepAliveCount; ++i) { - DruidConnectionHolder item = keepAliveConnections[i]; - Connection connection = item.getConnection(); + DruidConnectionHolder holer = keepAliveConnections[i]; + Connection connection = holer.getConnection(); boolean validate = false; try { this.validateConnection(connection); validate = true; } catch (Throwable error) { + if (LOG.isDebugEnabled()) { + LOG.debug("keepAliveErr", error); + } // skip } - item.setLastActiveTimeMillis(System.currentTimeMillis()); if (validate) { - put(item); + holer.setLastActiveTimeMillis(System.currentTimeMillis()); + put(holer); + keepAliveCheckOkCount.incrementAndGet(); } else { + keepAliveCheckErrCount.incrementAndGet(); JdbcUtils.close(connection); } } diff --git a/src/test/java/com/alibaba/druid/bvt/pool/KeepAliveTest.java b/src/test/java/com/alibaba/druid/bvt/pool/KeepAliveTest.java new file mode 100644 index 0000000000..74a39ff8b7 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/pool/KeepAliveTest.java @@ -0,0 +1,53 @@ +package com.alibaba.druid.bvt.pool; + +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.util.JdbcUtils; +import junit.framework.TestCase; + +import java.sql.Connection; +import java.util.Properties; + +/** + * Created by wenshao on 21/01/2017. + */ +public class KeepAliveTest extends TestCase { + private DruidDataSource dataSource; + + protected void setUp() throws Exception { + dataSource = new DruidDataSource(); + dataSource.setUrl("jdbc:mock:x1"); + dataSource.setPoolPreparedStatements(true); + dataSource.setMinIdle(10); + dataSource.setMaxActive(20); +// dataSource.setMinEvictableIdleTimeMillis(30000); +// dataSource.setMaxEvictableIdleTimeMillis(30000); + dataSource.setTimeBetweenEvictionRunsMillis(10); + dataSource.setFilters("log4j"); + dataSource.setValidationQuery("select 1"); + + Properties properties = new Properties(); + properties.put("druid.keepAlive", "true"); + dataSource.configFromPropety(properties); + } + + protected void tearDown() throws Exception { + JdbcUtils.close(dataSource); + } + + public void test_keepAlive() throws Exception { + assertTrue(dataSource.isKeepAlive()); + + Connection[] connections = new Connection[dataSource.getMaxActive()]; + for (int i = 0; i < connections.length; ++i) { + connections[i] = dataSource.getConnection(); + } + for (int i = 0; i < connections.length; ++i) { + connections[i].close(); + } + // assertEquals(dataSource.getMaxActive(), dataSource.getPoolingCount()); + + + + // Thread.sleep(1000 * 1000); + } +}