From 1dfe8112a7e5c9ef98414bb4c7f7d457b44ac3e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E9=93=81?= Date: Tue, 2 Feb 2016 16:04:42 +0800 Subject: [PATCH] improved DruidDataSource for profile --- .../druid/pool/DruidAbstractDataSource.java | 59 +++++++++++++++++-- .../druid/pool/DruidConnectionHolder.java | 26 +++++++- .../alibaba/druid/pool/DruidDataSource.java | 29 +++++---- .../druid/pool/DruidPooledConnection.java | 12 ++++ .../basic/PoolableCallableStatementTest.java | 2 +- .../basic/PoolablePreparedStatementTest.java | 2 +- .../pool/basic/PreparedStatementKeyTest.java | 2 +- .../bvt/pool/profile/ProfileEnableTest.java | 32 ++++++++++ 8 files changed, 142 insertions(+), 22 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/pool/profile/ProfileEnableTest.java diff --git a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java index 8197167758..2d42f3678d 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java @@ -1393,7 +1393,7 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements return conn; } - public Connection createPhysicalConnection() throws SQLException { + public PhysicalConnectionInfo createPhysicalConnection() throws SQLException { String url = this.getUrl(); Properties connectProperties = getConnectProperties(); @@ -1436,18 +1436,22 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements Connection conn; - long startNano = System.nanoTime(); - + long connectStartNanos = System.nanoTime(); + long connectedNanos, initedNanos, validatedNanos; try { conn = createPhysicalConnection(url, physicalConnectProperties); + connectedNanos = System.nanoTime(); if (conn == null) { throw new SQLException("connect error, url " + url + ", driverClass " + this.driverClass); } initPhysicalConnection(conn); + initedNanos = System.nanoTime(); validateConnection(conn); + validatedNanos = System.nanoTime(); + createError = null; } catch (SQLException ex) { createErrorCount.incrementAndGet(); @@ -1465,11 +1469,11 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements createErrorCount.incrementAndGet(); throw ex; } finally { - long nano = System.nanoTime() - startNano; + long nano = System.nanoTime() - connectStartNanos; createTimespan += nano; } - return conn; + return new PhysicalConnectionInfo(conn, connectStartNanos, connectedNanos, initedNanos, validatedNanos); } public void initPhysicalConnection(Connection conn) throws SQLException { @@ -1753,4 +1757,49 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements this.maxCreateTaskCount = maxCreateTaskCount; } + + static class PhysicalConnectionInfo { + private Connection connection; + private long connectStartNanos; + private long connectedNanos; + private long initedNanos; + private long validatedNanos; + + public PhysicalConnectionInfo(Connection connection // + , long connectStartNanos // + , long connectedNanos // + , long initedNanos // + , long validatedNanos) { + this.connection = connection; + + this.connectStartNanos = connectStartNanos; + this.connectedNanos = connectedNanos; + this.initedNanos = initedNanos; + this.validatedNanos = validatedNanos; + } + + public Connection getPhysicalConnection() { + return connection; + } + + public long getConnectStartNanos() { + return connectStartNanos; + } + + public long getConnectedNanos() { + return connectedNanos; + } + + public long getInitedNanos() { + return initedNanos; + } + + public long getValidatedNanos() { + return validatedNanos; + } + + public long getConnectNanoSpan() { + return connectedNanos - connectStartNanos; + } + } } diff --git a/src/main/java/com/alibaba/druid/pool/DruidConnectionHolder.java b/src/main/java/com/alibaba/druid/pool/DruidConnectionHolder.java index ebba909fd8..82cfc615a6 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidConnectionHolder.java +++ b/src/main/java/com/alibaba/druid/pool/DruidConnectionHolder.java @@ -15,6 +15,7 @@ */ package com.alibaba.druid.pool; +import com.alibaba.druid.pool.DruidAbstractDataSource.PhysicalConnectionInfo; import com.alibaba.druid.support.logging.Log; import com.alibaba.druid.support.logging.LogFactory; import com.alibaba.druid.util.JdbcConstants; @@ -47,6 +48,10 @@ public final class DruidConnectionHolder { private final long connectTimeMillis; private transient long lastActiveTimeMillis; private long useCount = 0; + + private long lastNotEmptyWaitNanos; + + private final long createNanoSpan; private PreparedStatementPool statementPool; @@ -65,11 +70,16 @@ public final class DruidConnectionHolder { private boolean discard = false; public static boolean holdabilityUnsupported = false; + + public DruidConnectionHolder(DruidAbstractDataSource dataSource, PhysicalConnectionInfo pyConnectInfo) throws SQLException { + this(dataSource, pyConnectInfo.getPhysicalConnection(), pyConnectInfo.getConnectNanoSpan()); + } - public DruidConnectionHolder(DruidAbstractDataSource dataSource, Connection conn) throws SQLException{ + public DruidConnectionHolder(DruidAbstractDataSource dataSource, Connection conn, long connectNanoSpan) throws SQLException{ this.dataSource = dataSource; this.conn = conn; + this.createNanoSpan = connectNanoSpan; this.connectTimeMillis = System.currentTimeMillis(); this.lastActiveTimeMillis = connectTimeMillis; @@ -256,6 +266,20 @@ public final class DruidConnectionHolder { public void setDiscard(boolean discard) { this.discard = discard; } + + + public long getCreateNanoSpan() { + return createNanoSpan; + } + + + public long getLastNotEmptyWaitNanos() { + return lastNotEmptyWaitNanos; + } + + protected void setLastNotEmptyWaitNanos(long lastNotEmptyWaitNanos) { + this.lastNotEmptyWaitNanos = lastNotEmptyWaitNanos; + } public String toString() { StringBuilder buf = new StringBuilder(); diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index ab2f687b7e..7ce556208f 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -166,7 +166,7 @@ public class DruidDataSource extends DruidAbstractDataSource public static ThreadLocal waitNanosLocal = new ThreadLocal(); private boolean logDifferentThread = true; - + public DruidDataSource(){ this(false); } @@ -640,8 +640,8 @@ public class DruidDataSource extends DruidAbstractDataSource try { // init connections for (int i = 0, size = getInitialSize(); i < size; ++i) { - Connection conn = createPhysicalConnection(); - DruidConnectionHolder holder = new DruidConnectionHolder(this, conn); + PhysicalConnectionInfo pyConnectInfo = createPhysicalConnection(); + DruidConnectionHolder holder = new DruidConnectionHolder(this, pyConnectInfo); connections[poolingCount] = holder; incrementPoolingCount(); } @@ -1530,6 +1530,9 @@ public class DruidDataSource extends DruidAbstractDataSource decrementPoolingCount(); DruidConnectionHolder last = connections[poolingCount]; connections[poolingCount] = null; + + long waitNanos = nanos - estimate; + last.setLastNotEmptyWaitNanos(waitNanos); return last; } @@ -1726,10 +1729,10 @@ public class DruidDataSource extends DruidAbstractDataSource return removeAbandonedCount; } - protected void put(Connection connection) { + protected void put(PhysicalConnectionInfo physicalConnectionInfo) { DruidConnectionHolder holder = null; try { - holder = new DruidConnectionHolder(DruidDataSource.this, connection); + holder = new DruidConnectionHolder(DruidDataSource.this, physicalConnectionInfo); } catch (SQLException ex) { lock.lock(); try { @@ -1799,10 +1802,10 @@ public class DruidDataSource extends DruidAbstractDataSource lock.unlock(); } - Connection connection = null; + PhysicalConnectionInfo physicalConnection = null; try { - connection = createPhysicalConnection(); + physicalConnection = createPhysicalConnection(); } catch (SQLException e) { LOG.error("create connection error, url: " + jdbcUrl, e); @@ -1837,11 +1840,11 @@ public class DruidDataSource extends DruidAbstractDataSource break; } - if (connection == null) { + if (physicalConnection == null) { continue; } - put(connection); + put(physicalConnection); break; } } @@ -1886,7 +1889,7 @@ public class DruidDataSource extends DruidAbstractDataSource lock.unlock(); } - Connection connection = null; + PhysicalConnectionInfo connection = null; try { connection = createPhysicalConnection(); @@ -2704,8 +2707,8 @@ public class DruidDataSource extends DruidAbstractDataSource DruidConnectionHolder holder; try { - Connection conn = createPhysicalConnection(); - holder = new DruidConnectionHolder(this, conn); + PhysicalConnectionInfo pyConnInfo = createPhysicalConnection(); + holder = new DruidConnectionHolder(this, pyConnInfo); } catch (SQLException e) { LOG.error("fill connection error, url: " + this.jdbcUrl, e); connectErrorCount.incrementAndGet(); @@ -2774,7 +2777,7 @@ public class DruidDataSource extends DruidAbstractDataSource CreateConnectionTask task = new CreateConnectionTask(); createScheduler.submit(task); } - + @Override public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception { //do nothing diff --git a/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java b/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java index 962872c896..c9744f93f7 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java +++ b/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java @@ -1182,4 +1182,16 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql. public void abandond() { this.abandoned = true; } + + public long getPhysicalConnectNanoSpan() { + return this.holder.getCreateNanoSpan(); + } + + public long getPhysicalConnectionUsedCount() { + return this.holder.getUseCount(); + } + + public long getConnectNotEmptyWaitNanos() { + return this.holder.getLastNotEmptyWaitNanos(); + } } diff --git a/src/test/java/com/alibaba/druid/bvt/pool/basic/PoolableCallableStatementTest.java b/src/test/java/com/alibaba/druid/bvt/pool/basic/PoolableCallableStatementTest.java index 69129dd706..07e0a50f9b 100644 --- a/src/test/java/com/alibaba/druid/bvt/pool/basic/PoolableCallableStatementTest.java +++ b/src/test/java/com/alibaba/druid/bvt/pool/basic/PoolableCallableStatementTest.java @@ -49,7 +49,7 @@ public class PoolableCallableStatementTest extends TestCase { protected void setUp() throws Exception { MockConnection mockConn = new MockConnection(); - DruidConnectionHolder connHolder = new DruidConnectionHolder(dataSource, mockConn); + DruidConnectionHolder connHolder = new DruidConnectionHolder(dataSource, mockConn, 0); conn = new DruidPooledConnection(connHolder); raw = new MockCallableStatement(null, null); stmt = new DruidPooledCallableStatement(conn, new PreparedStatementHolder(new PreparedStatementKey("", null, diff --git a/src/test/java/com/alibaba/druid/bvt/pool/basic/PoolablePreparedStatementTest.java b/src/test/java/com/alibaba/druid/bvt/pool/basic/PoolablePreparedStatementTest.java index f83f0db007..7bd4e66a7c 100644 --- a/src/test/java/com/alibaba/druid/bvt/pool/basic/PoolablePreparedStatementTest.java +++ b/src/test/java/com/alibaba/druid/bvt/pool/basic/PoolablePreparedStatementTest.java @@ -45,7 +45,7 @@ public class PoolablePreparedStatementTest extends TestCase { protected void setUp() throws Exception { DruidDataSource dataSource = new DruidDataSource(); MockConnection mockConn = new MockConnection(); - DruidConnectionHolder connHolder = new DruidConnectionHolder(dataSource, mockConn); + DruidConnectionHolder connHolder = new DruidConnectionHolder(dataSource, mockConn, 0); DruidPooledConnection conn = new DruidPooledConnection(connHolder); raw = new MockPreparedStatement(null, null); diff --git a/src/test/java/com/alibaba/druid/bvt/pool/basic/PreparedStatementKeyTest.java b/src/test/java/com/alibaba/druid/bvt/pool/basic/PreparedStatementKeyTest.java index b03d26b88a..b3e06017ea 100644 --- a/src/test/java/com/alibaba/druid/bvt/pool/basic/PreparedStatementKeyTest.java +++ b/src/test/java/com/alibaba/druid/bvt/pool/basic/PreparedStatementKeyTest.java @@ -162,7 +162,7 @@ public class PreparedStatementKeyTest extends TestCase { MockConnection conn = new MockConnection(); PreparedStatementKey k1 = new PreparedStatementKey("x1", "c1", MethodType.M1); - PreparedStatementPool pool = new PreparedStatementPool(new DruidConnectionHolder(dataSource, conn)); + PreparedStatementPool pool = new PreparedStatementPool(new DruidConnectionHolder(dataSource, conn, 0)); MockPreparedStatement raw = new MockPreparedStatement(null, null); pool.put(new PreparedStatementHolder(k1, raw)); diff --git a/src/test/java/com/alibaba/druid/bvt/pool/profile/ProfileEnableTest.java b/src/test/java/com/alibaba/druid/bvt/pool/profile/ProfileEnableTest.java new file mode 100644 index 0000000000..db0e0c1e6b --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/pool/profile/ProfileEnableTest.java @@ -0,0 +1,32 @@ +package com.alibaba.druid.bvt.pool.profile; + +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.pool.DruidPooledConnection; + +import junit.framework.TestCase; + +public class ProfileEnableTest extends TestCase { + + private DruidDataSource dataSource; + + protected void setUp() throws Exception { + dataSource = new DruidDataSource(); + dataSource.setUrl("jdbc:mock:xxx"); + dataSource.setMaxWait(1000); + } + + protected void tearDown() throws Exception { + dataSource.close(); + } + + public void testDefault() throws Exception { + for (int i = 0; i < 10; ++i) { + DruidPooledConnection conn = dataSource.getConnection(); + System.out.println("physicalConnectNanoSpan : " + conn.getPhysicalConnectNanoSpan()); + System.out.println("physicalConnectionUsedCount : " + conn.getPhysicalConnectionUsedCount()); + System.out.println("connectNotEmptyWaitNanos : " + conn.getConnectNotEmptyWaitNanos()); + conn.close(); + } + } + +}