Druid无限重连与获取连接失败异常

在我的毕设系统中,由于是动态配置的数据源,所以在测试错误的连接信息的时候,发现druid会一直重连,log无限刷新。

通过debug看到druid的重试机制,如图:

···        
while(true) {
                PhysicalConnectionInfo connection;
                label344: {
                    while(true) {
                        try {
                            DruidDataSource.this.lock.lockInterruptibly();
                        } catch (InterruptedException var33) {
                            break;
                        }

                        long discardCount = DruidDataSource.this.discardCount;
                        boolean discardChanged = discardCount - lastDiscardCount > 0L;
                        lastDiscardCount = discardCount;

                        try {
                            boolean emptyWait = true;
                            if (DruidDataSource.this.createError != null && DruidDataSource.this.poolingCount == 0 && !discardChanged) {
                                emptyWait = false;
                            }

                            if (emptyWait && DruidDataSource.this.asyncInit && DruidDataSource.this.createCount < (long)DruidDataSource.this.initialSize) {
                                emptyWait = false;
                            }

                            if (emptyWait) {
                                if (DruidDataSource.this.poolingCount >= DruidDataSource.this.notEmptyWaitThreadCount && (!DruidDataSource.this.keepAlive || DruidDataSource.this.activeCount + DruidDataSource.this.poolingCount >= DruidDataSource.this.minIdle) && !DruidDataSource.this.isFailContinuous()) {
                                    DruidDataSource.this.empty.await();
                                }

                                if (DruidDataSource.this.activeCount + DruidDataSource.this.poolingCount >= DruidDataSource.this.maxActive) {
                                    DruidDataSource.this.empty.await();
                                    continue;
                                }
                            }
                        } catch (InterruptedException var31) {
                            DruidDataSource.this.lastCreateError = var31;
                            DruidDataSource.this.lastErrorTimeMillis = System.currentTimeMillis();
                            if (!DruidDataSource.this.closing) {
                                DruidDataSource.LOG.error("create connection Thread Interrupted, url: " + DruidDataSource.this.jdbcUrl, var31);
                            }
                            break;
                        } finally {
                            DruidDataSource.this.lock.unlock();
                        }

                        connection = null;

                        try {
                            connection = DruidDataSource.this.createPhysicalConnection();
                            break label344;
                        } catch (SQLException var28) {
                            DruidDataSource.LOG.error("create connection SQLException, url: " + DruidDataSource.this.jdbcUrl + ", errorCode " + var28.getErrorCode() + ", state " + var28.getSQLState(), var28);
                            ++errorCount;
                            if (errorCount <= DruidDataSource.this.connectionErrorRetryAttempts || DruidDataSource.this.timeBetweenConnectErrorMillis <= 0L) {
                                break label344;
                            }

                            DruidDataSource.this.setFailContinuous(true);
                            if (DruidDataSource.this.failFast) {
                                DruidDataSource.this.lock.lock();

                                try {
                                    DruidDataSource.this.notEmpty.signalAll();
                                } finally {
                                    DruidDataSource.this.lock.unlock();
                                }
                            }

                            if (!DruidDataSource.this.breakAfterAcquireFailure) {
                                try {
                                    Thread.sleep(DruidDataSource.this.timeBetweenConnectErrorMillis);
                                    break label344;
                                } catch (InterruptedException var27) {
                                }
                            }
                            break;
                        } catch (RuntimeException var29) {
                            DruidDataSource.LOG.error("create connection RuntimeException", var29);
                            DruidDataSource.this.setFailContinuous(true);
                        } catch (Error var30) {
                            DruidDataSource.LOG.error("create connection Error", var30);
                            DruidDataSource.this.setFailContinuous(true);
                            break;
                        }
                    }

                    return;
                }

                if (connection != null) {
                    boolean result = DruidDataSource.this.put(connection);
                    if (!result) {
                        JdbcUtils.close(connection.getPhysicalConnection());
                        DruidDataSource.LOG.info("put physical connection to pool failed.");
                    }

                    errorCount = 0;
                }
            }
···

发现druid的处理是写在一个死循环中,关键代码是:

···
DruidDataSource.LOG.error("create connection SQLException, url: " + DruidDataSource.this.jdbcUrl + ", errorCode " + var28.getErrorCode() + ", state " + var28.getSQLState(), var28);
++errorCount;
if (errorCount <= DruidDataSource.this.connectionErrorRetryAttempts || DruidDataSource.this.timeBetweenConnectErrorMillis <= 0L) {
    break label344;
}
···

可以发现connectionErrorRetryAttemptstimeBetweenConnectErrorMillis都是druid配置里的参数,

connectionErrorRetryAttempts连接出错后再尝试连接次数
timeBetweenConnectErrorMillis关闭空闲连接的检测时间间隔

若希望关闭重试,可将BreakAfterAcquireFailure设置为trueconnectionErrorRetryAttempts设置为0

但是当前的请求并不会得到返回,而是一直处在等待状态,继续debug,发现问题:

DruidDataSource.class中(第1949行),程序运行到这里就被阻塞了,而我想要获取这个异常信息。

···
try {
    this.notEmpty.await();
} finally {
    --this.notEmptyWaitThreadCount;
}
···

继续研究Druid的参数,发现可以设置maxWait来获取异常信息。

maxWait超时等待时间

这样的话就大可不必关闭重试了,毕竟正确的连接信息还是有重试的必要的。

通过debug可以发现,这便是我想要获得的异常信息。

···
try {
    if(ChangeDataSourceHelper.changeDataSource(dbInfo)) {
        List<String> lst = databaseStructureDao.databaseList();
        return new Response().success(lst);
    } else {
        return new Response().failure("get connection failed!");
    }
} catch (Exception e) {
    return new Response().failure(e.getCause().getCause().getMessage());
}
···

如果您想要查看我的源码,可以访问我在github中的项目Indestrutible_backend

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值