improved DruidDataSource for profile

This commit is contained in:
高铁
2016-02-02 16:04:42 +08:00
parent cdeec1f73c
commit 1dfe8112a7
8 changed files with 142 additions and 22 deletions
@@ -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;
}
}
}
@@ -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();
@@ -166,7 +166,7 @@ public class DruidDataSource extends DruidAbstractDataSource
public static ThreadLocal<Long> waitNanosLocal = new ThreadLocal<Long>();
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
@@ -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();
}
}
@@ -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,
@@ -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);
@@ -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));
@@ -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();
}
}
}