写点什么

Druid 连接池源码阅读 03

作者:石小天
  • 2022 年 5 月 13 日
  • 本文字数:2541 字

    阅读完需:约 8 分钟

获取连接

    @Override    public DruidPooledConnection getConnection() throws SQLException {        return getConnection(maxWait);    }
public DruidPooledConnection getConnection(long maxWaitMillis) throws SQLException { init();
if (filters.size() > 0) { FilterChainImpl filterChain = new FilterChainImpl(this); return filterChain.dataSource_connect(this, maxWaitMillis); } else { return getConnectionDirect(maxWaitMillis); } }
复制代码

maxWait 是获取连接时最长的等待时间,默认是-1。

如果 filters 不为空,就使用 filter 进行创建。

否则调用 getConnectionDirect()方法。

    public DruidPooledConnection getConnectionDirect(long maxWaitMillis) throws SQLException {        int notFullTimeoutRetryCnt = 0;        for (;;) {            // handle notFullTimeoutRetry            DruidPooledConnection poolableConnection;            try {                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;            }
if (testOnBorrow) { 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; }
if (testWhileIdle) { final DruidConnectionHolder holder = poolableConnection.holder; long currentTimeMillis = System.currentTimeMillis(); long lastActiveTimeMillis = holder.lastActiveTimeMillis; long lastExecTimeMillis = holder.lastExecTimeMillis; long lastKeepTimeMillis = holder.lastKeepTimeMillis;
if (checkExecuteTime && lastExecTimeMillis != lastActiveTimeMillis) { lastActiveTimeMillis = lastExecTimeMillis; }
if (lastKeepTimeMillis > lastActiveTimeMillis) { lastActiveTimeMillis = lastKeepTimeMillis; }
long idleMillis = currentTimeMillis - lastActiveTimeMillis;
long timeBetweenEvictionRunsMillis = this.timeBetweenEvictionRunsMillis;
if (timeBetweenEvictionRunsMillis <= 0) { timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; }
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; } } } }
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(); } }
if (!this.defaultAutoCommit) { poolableConnection.setAutoCommit(false); }
return poolableConnection; } }
复制代码

getConnectionDirect()方法内是一个大的 for 循环,通过 getConnectionInternal(maxWait)方法来获取一个 DruidPooledConnection。

如果捕捉到获取连接超时的异常,去判断 notFullTimeoutRetryCnt 这个参数是否小于设定的超时重试参数,并且在连接池未满的情况下继续进行重试。

如果重试次数已经足够或者此时连接池已经满了则将异常抛出去。

isFull 方法用来判断存在池子内的连接和活跃连接的数量是否大于等于最大

连接数 MaxActiveCount。


用户头像

石小天

关注

还未添加个人签名 2018.11.07 加入

还未添加个人简介

评论

发布
暂无评论
Druid 连接池源码阅读 03_石小天_InfoQ写作社区