1、重要参数
参数 | 含义 |
---|---|
connectionErrorRetryAttempts | 设置断连重连次数 |
breakAfterAcquireFailure | true向数据库请求物理连接失败后,不再进行重连,客户端对连接池的请求全部拒绝;false表示新的请求都会尝试去数据库请求连接,默认false |
notFullTimeoutRetryCount | 获取连接超时重试,若等于0,则不会重试 |
timeBetweenConnectErrorMillis | 创建连接出错并且次数超过connectionErrorRetryAttempts阈值时,createConnectionTask线程休眠时间 |
failFast | 直接快速失败 |
maxWait | 获取连接等待的超时时间,默认-1 |
2、maxWait
maxWait > 0,获取一个连接的多大等待时间,获取连接超时时可能会触发重新获取至少1次,还取决于另一个参数notFullTimeoutRetryCount。
public DruidPooledConnection getConnectionDirect(long maxWaitMillis) throws SQLException {
int notFullTimeoutRetryCnt = 0;
for (; ; ) {
// handle notFullTimeoutRetry
DruidPooledConnection poolableConnection;
try {
/*
将连接对象DruidConnectionHolder封装为DruidPooledConnection返回
获取连接的方式,1、直接创建物理连接;2、pollLast有效时间内获取连接;3、takeLast持续获取
*/
poolableConnection = getConnectionInternal(maxWaitMillis);
} catch (GetConnectionTimeoutException ex) {
// 超时重试次数 > 0 并且 连接池未满,则进行获取连接重试
if (notFullTimeoutRetryCnt <= this.notFullTimeoutRetryCount && !isFull()) {
notFullTimeoutRetryCnt++;
if (LOG.isWarnEnabled()) {
LOG.warn("get connection timeout retry : " + notFullTimeoutRetryCnt);
}
continue;
}
throw ex;
}
3、notFullTimeoutRetryCount
配置notFullTimeoutRetryCount > 0时,并且 池内借出的连接 + 可用连接 < 最大连接数,则进行重试操作。
public DruidPooledConnection getConnectionDirect(long maxWaitMillis) throws SQLException {
int notFullTimeoutRetryCnt = 0;
for (; ; ) {
// handle notFullTimeoutRetry
DruidPooledConnection poolableConnection;
try {
/*
将连接对象DruidConnectionHolder封装为DruidPooledConnection返回
获取连接的方式,1、直接创建物理连接;2、pollLast有效时间内获取连接;3、takeLast持续获取
*/
poolableConnection = getConnectionInternal(maxWaitMillis);
} catch (GetConnectionTimeoutException ex) {
// 超时重试次数 > 0 并且 连接池未满,则进行获取连接重试
if (notFullTimeoutRetryCnt <= this.notFullTimeoutRetryCount && !isFull()) {
notFullTimeoutRetryCnt++;
if (LOG.isWarnEnabled()) {
LOG.warn("get connection timeout retry : " + notFullTimeoutRetryCnt);
}
continue;
}
throw ex;
}
4、failFast / isFailContinuous()
异步创建物理连接时通过CreateConnectionTask线程去创建,假如创建连接发生错误,并且错误次数超过重试次数(connectionErrorRetryAttempts),那么failFast机制会唤醒所有等待拿连接的线程去获取连接,在getConnection的时候takeLast/pollLast(long nanos)会快速失败
if (failFast && isFailContinuous()) { throw new DataSourceNotAvailableException(createError); }
快速失败除了failFast还要一个重要条件isFailContinuous()
public boolean isFailContinuous() { return failContinuousUpdater.get(this) == 1; }
在创建连接失败 并且 超过重试次数后,会将failContinuous置为1,并且唤醒所有等待拿连接的线程去获取连接,目的是让线程快速失败掉并返回。
errorCount++;
if (errorCount > connectionErrorRetryAttempts && timeBetweenConnectErrorMillis > 0) {
// fail over retry attempts
setFailContinuous(true);
// 快速失败
if (failFast) {
lock.lock();
try {
notEmpty.signalAll();
} finally {
lock.unlock();
}
}
。。。
protected void setFailContinuous(boolean fail) {
// fail:多次连接失败后fail=true
if (fail) {
failContinuousTimeMillisUpdater.set(this, System.currentTimeMillis());
} else {
failContinuousTimeMillisUpdater.set(this, 0L);
}
// 将failContinuous原子性的置为1,在pollLast/takeLast中会快速失败
boolean currentState = failContinuousUpdater.get(this) == 1;
if (currentState == fail) {
return;
}
。。。