DruidCP源码阅读10 -- DruidDataSource断连重连

1、重要参数

参数含义
connectionErrorRetryAttempts设置断连重连次数
breakAfterAcquireFailuretrue向数据库请求物理连接失败后,不再进行重连,客户端对连接池的请求全部拒绝;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;
        }
。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zyc_2754

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值