分析DruidDataSource类中的方法getConnectionDirect( )
首先通过一个for循环自旋,确保连接的创建。
for (;;) {
// handle notFullTimeoutRetry
DruidPooledConnection poolableConnection;
try {
//调⽤getConnectionInternal 获取连接
poolableConnection = getConnectionInternal(maxWaitMillis);
} catch (GetConnectionTimeoutException ex) {
//超时异常处理,判断是否达到最⼤重试次数且连接池是否已满
if (notFullTimeoutRetryCnt <= this.notFullTimeoutRetryCount && !isFull()) {
notFullTimeoutRetryCnt++;
if (LOG.isWarnEnabled()) {
LOG.warn("get connection timeout retry : " + notFullTimeoutRetryCnt);
}
// 再次获取连接,尝试次数++
continue;
}
throw ex;
}
// 后续代码
}
通过自旋的方式获取到连接,之后对连接进行检测。
testOnBorrow
if (testOnBorrow) { // 默认是false
// 通过validationQuery测试连接是否正常
boolean validate = testConnectionInternal(poolableConnection.holder, poolableConnection.conn);
if (!validate) {
if (LOG.isDebugEnabled()) {
LOG.debug("skip not validate connection.");
}
// ?
discardConnection(poolableConnection.holder);
continue;
}
} else {
// 检查连接是否关闭
if (poolableConnection.conn.isClosed()) {
discardConnection(poolableConnection.holder); // 传入null,避免重复关闭
continue;
}
testWhileIdle
if (testWhileIdle) {
。。。
// 如果连接空闲时间大于设置值,就测试validationQuery,验证连接是否有效
if (idleMillis >= timeBetweenEvictionRunsMillis
|| idleMillis < 0 // unexcepted branch
) {
boolean validate = testConnectionInternal(poolableConnection.holder, poolableConnection.conn);
if (!validate) {
if (LOG.isDebugEnabled()) {
LOG.debug("skip not validate connection.");
}
discardConnection(poolableConnection.holder);
continue;
}
}
。。。
}
}
检测过程都会调用 testConnectionInternal(poolableConnection.holder, poolableConnection.conn)
进行测试。
removeAbandoned
如果有线程从Druid中获取到了连接并没有及时归还,那么Druid就会定期检测该连接是否会处于运⾏状态,如果不处于运⾏状态,则被获取时间超过removeAbandonedTimeoutMillis
就会强制回收该连接。
if (removeAbandoned) {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
poolableConnection.connectStackTrace = stackTrace;
poolableConnection.setConnectedTimeNano();
poolableConnection.traceEnable = true;
activeConnectionLock.lock();
try {
activeConnections.put(poolableConnection, PRESENT);
} finally {
activeConnectionLock.unlock();
}
}
defaultAutoCommit
最后设置是否自动commit,并返回通过poolableConnection = getConnectionInternal(maxWaitMillis)
创建的连接
if (!this.defaultAutoCommit) {
poolableConnection.setAutoCommit(false);
}
return poolableConnection;
问题
- 参数(testOnBorrow…)在哪里设置的?
testConnectionInternal()
怎么进行连接验证?discardConnection()
有什么作用?