From 160320f396b5d84d2ba879c8ae9f5d96b76f388d Mon Sep 17 00:00:00 2001 From: wenshao Date: Sat, 21 Jan 2017 14:38:04 +0800 Subject: [PATCH] DruidDataSource add keepAlive support. --- .../alibaba/druid/pool/DruidDataSource.java | 72 ++++++++++++++++--- .../com/alibaba/druid/bvt/pool/TestIdle.java | 2 +- 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index c2254b911b..a36b06d8b5 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -132,6 +132,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat // private DruidConnectionHolder[] evictConnections; + private DruidConnectionHolder[] keepAliveConnections; // threads private ScheduledFuture destroySchedulerFuture; @@ -164,6 +165,8 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat private boolean logDifferentThread = true; + private boolean keepAlive = false; + public DruidDataSource(){ this(false); } @@ -313,6 +316,12 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } } } + { + Boolean value = getBoolean(properties, "druid.keepAlive"); + if (value != null) { + this.setKeepAlive(value); + } + } } public boolean isUseGlobalDataSourceStat() { @@ -323,6 +332,14 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat this.useGlobalDataSourceStat = useGlobalDataSourceStat; } + public boolean isKeepAlive() { + return keepAlive; + } + + public void setKeepAlive(boolean keepAlive) { + this.keepAlive = keepAlive; + } + public String getInitStackTrace() { return initStackTrace; } @@ -491,9 +508,11 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat if (maxActive > allCount) { this.connections = Arrays.copyOf(this.connections, maxActive); evictConnections = new DruidConnectionHolder[maxActive]; + keepAliveConnections = new DruidConnectionHolder[maxActive]; } else { this.connections = Arrays.copyOf(this.connections, allCount); evictConnections = new DruidConnectionHolder[allCount]; + keepAliveConnections = new DruidConnectionHolder[allCount]; } this.maxActive = maxActive; @@ -674,6 +693,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat connections = new DruidConnectionHolder[maxActive]; evictConnections = new DruidConnectionHolder[maxActive]; + keepAliveConnections = new DruidConnectionHolder[maxActive]; SQLException connectError = null; @@ -1815,6 +1835,10 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat return false; } + return put(holder); + } + + private boolean put(DruidConnectionHolder holder) { lock.lock(); try { if (poolingCount >= maxActive) { @@ -1842,7 +1866,6 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } finally { lock.unlock(); } - return true; } @@ -2256,10 +2279,14 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat @Override public void shrink() { - shrink(false); + shrink(false, false); } public void shrink(boolean checkTime) { + shrink(checkTime, keepAlive); + } + + public void shrink(boolean checkTime, boolean keepAlive) { try { lock.lockInterruptibly(); } catch (InterruptedException e) { @@ -2267,6 +2294,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } int evictCount = 0; + int keepAliveCount = 0; try { if (!inited) { return; @@ -2296,6 +2324,8 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat evictConnections[evictCount++] = connection; } else if (idleMillis > maxEvictableIdleTimeMillis) { evictConnections[evictCount++] = connection; + } else { + keepAliveConnections[keepAliveCount++] = connection; } } else { if (i < checkCount) { @@ -2306,7 +2336,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } } - int removeCount = evictCount; + int removeCount = evictCount + keepAliveCount; if (removeCount > 0) { System.arraycopy(connections, removeCount, connections, 0, poolingCount - removeCount); Arrays.fill(connections, poolingCount - removeCount, poolingCount, null); @@ -2316,13 +2346,37 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat lock.unlock(); } - for (int i = 0; i < evictCount; ++i) { - DruidConnectionHolder item = evictConnections[i]; - Connection connection = item.getConnection(); - JdbcUtils.close(connection); - destroyCount.incrementAndGet(); + if (evictCount > 0) { + for (int i = 0; i < evictCount; ++i) { + DruidConnectionHolder item = evictConnections[i]; + Connection connection = item.getConnection(); + JdbcUtils.close(connection); + destroyCount.incrementAndGet(); + } + Arrays.fill(evictConnections, null); + } + + if (keepAliveCount > 0) { + for (int i = 0; i < keepAliveCount; ++i) { + DruidConnectionHolder item = keepAliveConnections[i]; + Connection connection = item.getConnection(); + + boolean validate = false; + try { + this.validateConnection(connection); + validate = true; + } catch (Throwable error) { + // skip + } + + if (validate) { + put(item); + } else { + JdbcUtils.close(connection); + } + } + Arrays.fill(keepAliveConnections, null); } - Arrays.fill(evictConnections, null); } public int getWaitThreadCount() { diff --git a/src/test/java/com/alibaba/druid/bvt/pool/TestIdle.java b/src/test/java/com/alibaba/druid/bvt/pool/TestIdle.java index 520386d5d6..87568e2631 100644 --- a/src/test/java/com/alibaba/druid/bvt/pool/TestIdle.java +++ b/src/test/java/com/alibaba/druid/bvt/pool/TestIdle.java @@ -107,7 +107,7 @@ public class TestIdle extends TestCase { Thread.sleep(dataSource.getMinEvictableIdleTimeMillis() * 2); Assert.assertEquals(0, driver.getConnections().size()); - Assert.assertEquals(1, dataSource.getPoolingCount()); + Assert.assertEquals(0, dataSource.getPoolingCount()); { Connection conn = dataSource.getConnection(); Assert.assertEquals(1, dataSource.getActiveCount());