Druid04-获取连接

1、获取连接和初始化

在这里插入图片描述
  连接池内的连接数等于0,则唤醒创建物理连接的线程或任务,并将当前线程阻塞,当连接被创建或回收后唤醒被阻塞的线程,其次被阻塞的线程支持中断。

2、获取连接

    获取连接的时候也会先去检查一下连接池是否已经初始化,如果没有初始化则先进行初始化。

    public DruidPooledConnection getConnection(long maxWaitMillis) throws SQLException {
        //maxWaitMillis 从连接池获取连接最大等待时间(默认-1 一直等待) 
        init();
        if (filters.size() > 0) {
            //Filter被加载则通过责任链的方式调用
            FilterChainImpl filterChain = new FilterChainImpl(this);
            return filterChain.dataSource_connect(this, maxWaitMillis);
        } else {
            //使用直接获取连接的方式
            return getConnectionDirect(maxWaitMillis);
        }
    }
3、责任链执行
	//Filter开始下标
	protected int                 pos = 0;
	//连接池对象
    private final DataSourceProxy dataSource;
	//Filter的Size
    private final int             filterSize; 

	//获取连接会创建新的对象执行责任链
    public FilterChainImpl(DataSourceProxy dataSource){
        this.dataSource = dataSource;
        this.filterSize = getFilters().size();
    }

	//获取Filter之后pos+1
	private Filter nextFilter() {
        return getFilters().get(pos++);
    }

	//责任链执行
    public DruidPooledConnection dataSource_connect(DruidDataSource dataSource, long maxWaitMillis) 
        throws SQLException {
        //每次从0开始执行执行后pos+1
        if (this.pos < filterSize) {
            //通过递归方式调用
            DruidPooledConnection conn = nextFilter().dataSource_getConnection(this, dataSource, 
                                                                               		maxWaitMillis);
            return conn;
        }
        //责任链执行完后直接获取连接
        return dataSource.getConnectionDirect(maxWaitMillis);
    }

	//StatFilter执行回调到chain获取到连接后在执行
    public DruidPooledConnection dataSource_getConnection(FilterChain chain, DruidDataSource dataSource,
                                                          long maxWaitMillis) throws SQLException {
        //回调到chain来执行
        DruidPooledConnection conn = chain.dataSource_connect(dataSource, maxWaitMillis);
        if (conn != null) {
            conn.setConnectedTimeNano();
            StatFilterContext.getInstance().pool_connection_open();
        }
        return conn;
    }
4、getConnectionDirect
public DruidPooledConnection getConnectionDirect(long maxWaitMillis) throws SQLException {
        int notFullTimeoutRetryCnt = 0;
    	//获取连接异常或判断不可用则会重新获取连接
        for (;;) {
            DruidPooledConnection poolableConnection;
            try {
                //获取连接
                poolableConnection = getConnectionInternal(maxWaitMillis);
            } catch (GetConnectionTimeoutException ex) {
                //判断是否重试
                if (notFullTimeoutRetryCnt <= this.notFullTimeoutRetryCount && !isFull()) {  
                    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()) {
                    //将连接close
                    discardConnection(poolableConnection.holder); 
                    continue;
                }
				//测试连接的空闲时间
                if (testWhileIdle) {
                    ...
					//空闲时间>=timeBetweenEvictionRunsMillis (默认1分钟)
                    if (idleMillis >= timeBetweenEvictionRunsMillis || idleMillis < 0 ) {
                        //执行检测连接是否有效
                        boolean validate = testConnectionInternal(poolableConnection.holder, poolableConnection.conn);
                        if (!validate) {
                            if (LOG.isDebugEnabled()) {
                                LOG.debug("skip not validate connection.");
                            }
                            //连接不可以则将连接丢弃
                            discardConnection(poolableConnection.holder);
                             continue;
                        }
                    }
                }
            }
			//配置连接回收
            if (removeAbandoned) {
              	...
                try {
                    //将连接put到activeConnections Map中
                    activeConnections.put(poolableConnection, PRESENT);
                } finally {
                    activeConnectionLock.unlock();
                }
            }
            if (!this.defaultAutoCommit) {
                poolableConnection.setAutoCommit(false);
            }
            //返回最终的连接对象
            return poolableConnection;
        }
    }

    testWhileIdle 申请连接的时候检测是否有效。
    timeBetweenEvictionRunsMillis 连接空闲时间超过则测试连接的有效性,默认1分钟。

5、getConnectionInternal
private DruidPooledConnection getConnectionInternal(long maxWait) throws SQLException {
    	//判断连接池是否关闭
        if (closed) {
    		...
			  throw new DataSourceClosedException();
        }
		//判断连接池是否禁用
        if (!enable) {
           	...
            throw new DataSourceDisableException();
        }

        final long nanos = TimeUnit.MILLISECONDS.toNanos(maxWait);
        final int maxWaitThreadCount = this.maxWaitThreadCount;
        DruidConnectionHolder holder;
        for (boolean createDirect = false;;) {
			  //创建连接的标志
              if (createDirect) {
                createStartNanosUpdater.set(this, System.nanoTime());
                if (creatingCountUpdater.compareAndSet(this, 0, 1)) {
                    //使用创建线程池的定时任务创建连接
                    PhysicalConnectionInfo pyConnInfo = DruidDataSource.this.createPhysicalConnection();
               		...
                }
            }
            ...
            try {
                //获取连接池时先获取锁
                lock.lockInterruptibly();
            } catch (InterruptedException e) {
                connectErrorCountUpdater.incrementAndGet(this);
                throw new SQLException("interrupt", e);
            }
            try {
                //连接不够用时最多让多少线程发生阻塞(默认-1)
                if (maxWaitThreadCount > 0
                        && notEmptyWaitThreadCount >= maxWaitThreadCount) {
                    connectErrorCountUpdater.incrementAndGet(this);
                    throw new SQLException("maxWaitThreadCount " + maxWaitThreadCount + ", current wait Thread count " + lock.getQueueLength());
                }
				//发生致命错误
                if (onFatalError
                        && onFatalErrorMaxActive > 0
                        && activeCount >= onFatalErrorMaxActive) {
                    connectErrorCountUpdater.incrementAndGet(this);

                    StringBuilder errorMsg = new StringBuilder();
                    errorMsg.append("onFatalError, activeCount ")
                            .append(activeCount)
                            .append(", onFatalErrorMaxActive ")
                            .append(onFatalErrorMaxActive);
                    ...
                    throw new SQLException(errorMsg.toString(), lastFatalError);
                }

                connectCount++;
                //创建线程的线程不为空,并且线程池连接数等于0,并且活动线程小于最大线程
                if (createScheduler != null
                        && poolingCount == 0
                        && activeCount < maxActive
                        && creatingCountUpdater.get(this) == 0
                        && createScheduler instanceof ScheduledThreadPoolExecutor) {
                    ScheduledThreadPoolExecutor executor = (ScheduledThreadPoolExecutor) createScheduler;
                    if (executor.getQueue().size() > 0) {
                        //将创建连接的状态设为true,结束本次循环
                        createDirect = true;
                        continue;
                    }
                }
                //从连接池获取连接
                if (maxWait > 0) {
                    holder = pollLast(nanos);
                } else {
                    holder = takeLast();
                }
                if (holder != null) {
                    if (holder.discard) {
                        continue;
                    }
                    //活动线程+1
                    activeCount++;
                    holder.active = true;
                    if (activeCount > activePeak) {
                        activePeak = activeCount;
                        activePeakTime = System.currentTimeMillis();
                    }
                }
            } catch (InterruptedException e) {
                connectErrorCountUpdater.incrementAndGet(this);
                throw new SQLException(e.getMessage(), e);
            } catch (SQLException e) {
                connectErrorCountUpdater.incrementAndGet(this);
                throw e;
            } finally {
                lock.unlock();
            }

            break;
        }
    	//未获得连接对象,抛出异常
        if (holder == null) {
            long waitNanos = waitNanosLocal.get();
            final long activeCount;
            final long maxActive;
            final long creatingCount;
            final long createStartNanos;
            final long createErrorCount;
            final Throwable createError;
            try {
                lock.lock();
                activeCount = this.activeCount;
                maxActive = this.maxActive;
                creatingCount = this.creatingCount;
                createStartNanos = this.createStartNanos;
                createErrorCount = this.createErrorCount;
                createError = this.createError;
            } finally {
                lock.unlock();
            }
            StringBuilder buf = new StringBuilder(128);
            buf.append("wait millis ")//
               .append(waitNanos / (1000 * 1000))//
               .append(", active ").append(activeCount)//
               .append(", maxActive ").append(maxActive)//
               .append(", creating ").append(creatingCount);
            if (creatingCount > 0 && createStartNanos > 0) {
                long createElapseMillis = (System.nanoTime() - createStartNanos) / (1000 * 1000);
                if (createElapseMillis > 0) {
                    buf.append(", createElapseMillis ").append(createElapseMillis);
                }
            }
            if (createErrorCount > 0) {
                buf.append(", createErrorCount ").append(createErrorCount);
            }

            List<JdbcSqlStatValue> sqlList = this.getDataSourceStat().getRuningSqlList();
            for (int i = 0; i < sqlList.size(); ++i) {
                if (i != 0) {
                    buf.append('\n');
                } else {
                    buf.append(", ");
                }
                JdbcSqlStatValue sql = sqlList.get(i);
                buf.append("runningSqlCount ").append(sql.getRunningCount());
                buf.append(" : ");
                buf.append(sql.getSql());
            }
            String errorMessage = buf.toString();
            //获取连接超时异常
            if (createError != null) {
                throw new GetConnectionTimeoutException(errorMessage, createError);
            } else {
                throw new GetConnectionTimeoutException(errorMessage);
            }
        }
		//连接次数+1
        holder.incrementUseCount();
        DruidPooledConnection poolalbeConnection = new DruidPooledConnection(holder);
        return poolalbeConnection;
    }
6、从连接池获取连接
DruidConnectionHolder takeLast() throws InterruptedException, SQLException {
    try {
        //可用的连接 == 0
        while (poolingCount == 0) {
            //唤醒创建线程池的线程
            emptySignal(); 
            if (failFast && isFailContinuous()) {
                throw new DataSourceNotAvailableException(createError);
            }
            notEmptyWaitThreadCount++;
            if (notEmptyWaitThreadCount > notEmptyWaitThreadPeak) {
                notEmptyWaitThreadPeak = notEmptyWaitThreadCount;
            }
            try {
                //将当前线程阻塞,通过回收或创建者唤醒
                notEmpty.await(); 
            } finally {
                notEmptyWaitThreadCount--;
            }
            notEmptyWaitCount++;

            if (!enable) {
                connectErrorCountUpdater.incrementAndGet(this);
                if (disableException != null) {
                    throw disableException;
                }
                throw new DataSourceDisableException();
            }
        }
    } catch (InterruptedException ie) {
        notEmpty.signal(); // propagate to non-interrupted thread
        notEmptySignalCount++;
        throw ie;
    }
    
	//连接对象返回,将可用连接数减一,并且将连接池对应的位置设为空
    decrementPoolingCount();
    DruidConnectionHolder last = connections[poolingCount];
    connections[poolingCount] = null;
    return last;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值