From daef1b47cf99e4eb7852f06c784268782424ef49 Mon Sep 17 00:00:00 2001 From: "shaojin.wensj" Date: Sat, 6 Apr 2019 15:28:58 +0800 Subject: [PATCH] bug fixed for keepAlive --- .../druid/pool/DruidAbstractDataSource.java | 15 +++++- .../druid/pool/DruidConnectionHolder.java | 9 +++- .../alibaba/druid/pool/DruidDataSource.java | 54 +++++++++++++++---- .../druid/pool/DruidPooledStatement.java | 5 ++ 4 files changed, 72 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java index 3da39f81b9..1027a6e861 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java @@ -153,6 +153,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 keepAliveBetweenTimeMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS * 2; protected volatile long phyTimeoutMillis = DEFAULT_PHY_TIMEOUT_MILLIS; protected volatile long phyMaxUseCount = -1; @@ -769,7 +770,19 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; } - + + public long getKeepAliveBetweenTimeMillis() { + return keepAliveBetweenTimeMillis; + } + + public void setKeepAliveBetweenTimeMillis(long keepAliveBetweenTimeMillis) { + if (keepAliveBetweenTimeMillis < 1000 * 30) { + LOG.error("keepAliveBetweenTimeMillis should be greater than 30000"); + } + + this.keepAliveBetweenTimeMillis = keepAliveBetweenTimeMillis; + } + public long getMaxEvictableIdleTimeMillis() { return maxEvictableIdleTimeMillis; } diff --git a/src/main/java/com/alibaba/druid/pool/DruidConnectionHolder.java b/src/main/java/com/alibaba/druid/pool/DruidConnectionHolder.java index 0778659e07..26b1f3cf22 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidConnectionHolder.java +++ b/src/main/java/com/alibaba/druid/pool/DruidConnectionHolder.java @@ -51,6 +51,7 @@ public final class DruidConnectionHolder { protected final List statementEventListeners = new CopyOnWriteArrayList(); protected final long connectTimeMillis; protected volatile long lastActiveTimeMillis; + protected volatile long lastKeepTimeMillis; protected volatile long lastValidTimeMillis; protected long useCount = 0; private long keepAliveCheckCount = 0; @@ -345,7 +346,13 @@ public final class DruidConnectionHolder { if (lastActiveTimeMillis > 0) { buf.append(", LastActiveTime:\""); - buf.append(Utils.toString(new Date(this.lastActiveTimeMillis))); + buf.append(Utils.toString(new Date(lastActiveTimeMillis))); + buf.append("\""); + } + + if (lastKeepTimeMillis > 0) { + buf.append(", LastKeepTimeMillis:\""); + buf.append(Utils.toString(new Date(lastKeepTimeMillis))); buf.append("\""); } diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index 529255664d..b8a7ad50fa 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -407,6 +407,17 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat this.setKeepAlive(value); } } + { + String property = properties.getProperty("druid.keepAliveBetweenTimeMillis"); + if (property != null && property.length() > 0) { + try { + long value = Long.parseLong(property); + this.setKeepAliveBetweenTimeMillis(value); + } catch (NumberFormatException e) { + LOG.error("illegal property 'druid.keepAliveBetweenTimeMillis'", e); + } + } + } { Boolean value = getBoolean(properties, "druid.poolPreparedStatements"); if (value != null) { @@ -1354,8 +1365,15 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } if (testWhileIdle) { + final DruidConnectionHolder holder = poolableConnection.holder; long currentTimeMillis = System.currentTimeMillis(); - long lastActiveTimeMillis = poolableConnection.holder.lastActiveTimeMillis; + long lastActiveTimeMillis = holder.lastActiveTimeMillis; + long lastKeepTimeMillis = holder.lastKeepTimeMillis; + + if (lastKeepTimeMillis > lastActiveTimeMillis) { + lastActiveTimeMillis = lastKeepTimeMillis; + } + long idleMillis = currentTimeMillis - lastActiveTimeMillis; long timeBetweenEvictionRunsMillis = this.timeBetweenEvictionRunsMillis; @@ -1863,6 +1881,10 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat * close datasource */ public void close() { + if (LOG.isInfoEnabled()) { + LOG.info("{dataSource-" + this.getID() + "} closing ..."); + } + lock.lock(); try { if (this.closed) { @@ -2666,6 +2688,9 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } public class DestroyTask implements Runnable { + public DestroyTask() { + + } @Override public void run() { @@ -2869,15 +2894,23 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat long idleMillis = currentTimeMillis - connection.lastActiveTimeMillis; - if (idleMillis < minEvictableIdleTimeMillis) { + if (idleMillis < minEvictableIdleTimeMillis + && idleMillis < keepAliveBetweenTimeMillis + ) { break; } - if (checkTime && i < checkCount) { - evictConnections[evictCount++] = connection; - } else if (idleMillis > maxEvictableIdleTimeMillis) { - evictConnections[evictCount++] = connection; - } else if (keepAlive) { + if (idleMillis >= minEvictableIdleTimeMillis) { + if (checkTime && i < checkCount) { + evictConnections[evictCount++] = connection; + continue; + } else if (idleMillis > maxEvictableIdleTimeMillis) { + evictConnections[evictCount++] = connection; + continue; + } + } + + if (keepAlive && idleMillis >= keepAliveBetweenTimeMillis) { keepAliveConnections[keepAliveCount++] = connection; } } else { @@ -2911,7 +2944,6 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } if (keepAliveCount > 0) { - this.getDataSourceStat().addKeepAliveCheckCount(keepAliveCount); // keep order for (int i = keepAliveCount - 1; i >= 0; --i) { DruidConnectionHolder holer = keepAliveConnections[i]; @@ -2931,7 +2963,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat boolean discard = !validate; if (validate) { - holer.lastActiveTimeMillis = System.currentTimeMillis(); + holer.lastKeepTimeMillis = System.currentTimeMillis(); boolean putOk = put(holer); if (!putOk) { discard = true; @@ -2957,6 +2989,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } } } + this.getDataSourceStat().addKeepAliveCheckCount(keepAliveCount); Arrays.fill(keepAliveConnections, null); } } @@ -3134,6 +3167,9 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat if (connHolder.lastActiveTimeMillis > 0) { map.put("lastActiveTime", new Date(connHolder.lastActiveTimeMillis)); } + if (connHolder.lastKeepTimeMillis > 0) { + map.put("lastKeepTimeMillis", new Date(connHolder.lastKeepTimeMillis)); + } map.put("connectTime", new Date(connHolder.getTimeMillis())); map.put("holdability", connHolder.getUnderlyingHoldability()); map.put("transactionIsolation", connHolder.getUnderlyingTransactionIsolation()); diff --git a/src/main/java/com/alibaba/druid/pool/DruidPooledStatement.java b/src/main/java/com/alibaba/druid/pool/DruidPooledStatement.java index 4884d2319f..32875cb8df 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidPooledStatement.java +++ b/src/main/java/com/alibaba/druid/pool/DruidPooledStatement.java @@ -342,6 +342,11 @@ public class DruidPooledStatement extends PoolableWrapper implements Statement { long currentTimeMillis = System.currentTimeMillis(); long lastActiveTimeMillis = holder.lastActiveTimeMillis; + + if (lastActiveTimeMillis < holder.lastKeepTimeMillis) { + lastActiveTimeMillis = holder.lastKeepTimeMillis; + } + long idleMillis = currentTimeMillis - lastActiveTimeMillis; long lastValidIdleMillis = currentTimeMillis - holder.lastActiveTimeMillis;