Druid - 源码浅析(1) - 初始化

2 篇文章 0 订阅

实现类DruidDataSource:
     一些重要变量:

  •         private volatile DruidConnectionHolder[] connections;  //存连接的数组,不一定会满

  •         private int                              poolingCount              = 0; //池子中连接的总数

  •         private int                              activeCount               = 0; //活跃连接数

  •         private final CountDownLatch initedLatch = new CountDownLatch(2);   //初始化同步器

  •          //源于父类DruidAbstractDataSource的

  •          protected ReentrantLock                            lock; 

  •          protected Condition                                notEmpty;

  •          protected Condition                                empty;     //没有使用Sychronized;更灵活,配合condition使用,一个控制创建线程,一个控制销毁线程。

初始化:

    //加锁,只允许一个线程初始化,lock.lockInterruptibly()允许被中断等待,会抛出异常
    final ReentrantLock lock = this.lock;
        try {
            lock.lockInterruptibly();
        } catch (InterruptedException e) {
            throw new SQLException("interrupt", e);
        }
    初始化了一坨东西......
    ......
     
    //创建物理连接的地方.通过asyncInit配置同步或异步。
    if (createScheduler != null && asyncInit) {
             for (int i = 0; i < initialSize; ++i) {
                  createTaskCount++;
                  CreateConnectionTask task = new CreateConnectionTask(true);
                  this.createSchedulerFuture = createScheduler.submit(task);
                }
            } else if (!asyncInit) {
                // init connections## 创建物理连接,放到connections中
                while (poolingCount < initialSize) {
                    try {
                        PhysicalConnectionInfo pyConnectInfo = createPhysicalConnection();
                        DruidConnectionHolder holder = new DruidConnectionHolder(this, pyConnectInfo);
                        connections[poolingCount++] = holder;
                    } catch (SQLException ex) {
                        LOG.error("init datasource error, url: " + this.getUrl(), ex);
                        if (initExceptionThrow) {
                            connectError = ex;
                            break;
                        } else {
                            Thread.sleep(3000);
                        }
                    }
                }

                if (poolingCount > 0) {
                    poolingPeak = poolingCount;
                    poolingPeakTime = System.currentTimeMillis();
                }
            }
             
    createAndLogThread();
    //初始化创建和销毁线程,即调起这个线程进行各自工作,里面通过锁控制
    createAndStartCreatorThread();
    createAndStartDestroyThread();
    //这里用到了CountDownLatch(2),保证创建和摧毁线程都至少执行过一次才继续执行。
    initedLatch.await();
    

createAndStartCreatorThread():

protected void createAndStartCreatorThread() {
        if (createScheduler == null) {
            String threadName = "Druid-ConnectionPool-Create-" + System.identityHashCode(this);
            createConnectionThread = new CreateConnectionThread(threadName);
            createConnectionThread.start();
            return;
        }
        //countDownLacth -1
        initedLatch.countDown();
        init = true;
    }


public class CreateConnectionThread extends Thread {

        public CreateConnectionThread(String name){
            super(name);
            this.setDaemon(true);
        }

        public void run() {
            //countDownLacth -1
            initedLatch.countDown();

            long lastDiscardCount = 0;
            int errorCount = 0;
            for (;;) {
                // addLast
                try {
                    lock.lockInterruptibly();
                } catch (InterruptedException e2) {
                    break;
                }

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

                try {
                    //创建线程前的一些条件效验
                    boolean emptyWait = true;

                    if (createError != null
                            && poolingCount == 0
                            && !discardChanged) {
                        emptyWait = false;
                    }

                    if (emptyWait
                            && asyncInit && createCount < initialSize) {
                        emptyWait = false;
                    }

                    if (emptyWait) {
                        // 必须存在线程等待,才创建连接
                        if (poolingCount >= notEmptyWaitThreadCount //
                                && !(keepAlive && activeCount + poolingCount < minIdle)) {
                            empty.await();
                        }

                        // 防止创建超过maxActive数量的连接
                        if (activeCount + poolingCount >= maxActive) {
                            empty.await();
                            continue;
                        }
                    }

                } catch (InterruptedException e) {

                } finally {
                    lock.unlock();
                }

                PhysicalConnectionInfo connection = null;
                try {
                    connection = createPhysicalConnection();
                } catch (SQLException e) {
                   
                }

                //将connection包装成holdor放到connections[]中,这样包装是为了监控等功能吧.
                boolean result = put(connection);
  
            }
        }
    }

createAndStartDestroyThread():

protected void createAndStartDestroyThread() {
        destroyTask = new DestroyTask();

        if (destroyScheduler != null) {
            long period = timeBetweenEvictionRunsMillis;
            if (period <= 0) {
                period = 1000;
            }
            destroySchedulerFuture = destroyScheduler.scheduleAtFixedRate(destroyTask, period, period,
                                                                          TimeUnit.MILLISECONDS);
            initedLatch.countDown();
            return;
        }

        String threadName = "Druid-ConnectionPool-Destroy-" + System.identityHashCode(this);
        //这里new出了销毁连接的线程
        destroyConnectionThread = new DestroyConnectionThread(threadName);
        destroyConnectionThread.start();
    }

//DestroyConnectionThread
public class DestroyConnectionThread extends Thread {

        public DestroyConnectionThread(String name){
            super(name);
            this.setDaemon(true);
        }

        public void run() {
            //countDownLatch -1.
            initedLatch.countDown();

            for (;;) {
                // 从前面开始删除
                try {
                    if (closed) {
                        break;
                    }

                    if (timeBetweenEvictionRunsMillis > 0) {
                        Thread.sleep(timeBetweenEvictionRunsMillis);
                    } else {
                        Thread.sleep(1000); //
                    }

                    if (Thread.interrupted()) {
                        break;
                    }
                    //run里面是执行两个方法shrik()和removeAbandoned();
                    destroyTask.run();
                } catch (InterruptedException e) {
                    break;
                }
            }
        }

    }

//做一些超时和不可用连接的回收,调着连接池,当然初始化第一次时是直接return的
public void shrink(boolean checkTime, boolean keepAlive) {
        try {
            lock.lockInterruptibly();
        } catch (InterruptedException e) {
            return;
        }

        int evictCount = 0;
        int keepAliveCount = 0;
        try {
            if (!inited) {
                //未初始化直接return
                return;
            }

            final int checkCount = poolingCount - minIdle;
            final long currentTimeMillis = System.currentTimeMillis();
            for (int i = 0; i < poolingCount; ++i) {
                DruidConnectionHolder connection = connections[i];

                if (checkTime) {
                    //设置了物理连接时间并超时就回收
                    if (phyTimeoutMillis > 0) {
                        long phyConnectTimeMillis = currentTimeMillis - connection.connectTimeMillis;
                        if (phyConnectTimeMillis > phyTimeoutMillis) {
                            evictConnections[evictCount++] = connection;
                            continue;
                        }
                    }

                    long idleMillis = currentTimeMillis - connection.lastActiveTimeMillis;

                    if (idleMillis < minEvictableIdleTimeMillis) {
                        break;
                    }
                    //保证minIdle,空闲时间大于活跃时间回收
                    if (checkTime && i < checkCount) {
                        evictConnections[evictCount++] = connection;
                    } else if (idleMillis > maxEvictableIdleTimeMillis) {
                        evictConnections[evictCount++] = connection;
                    } else if (keepAlive) {
                        keepAliveConnections[keepAliveCount++] = connection;
                    }
                } else {
                    if (i < checkCount) {
                        evictConnections[evictCount++] = connection;
                    } else {
                        break;
                    }
                }
            }

            int removeCount = evictCount + keepAliveCount;
            if (removeCount > 0) {
                System.arraycopy(connections, removeCount, connections, 0, poolingCount - removeCount);
                Arrays.fill(connections, poolingCount - removeCount, poolingCount, null);
                poolingCount -= removeCount;
            }
            keepAliveCheckCount += keepAliveCount;
        } finally {
            lock.unlock();
        }
        //对evictConnections中的连接进行关闭
        if (evictCount > 0) {
            for (int i = 0; i < evictCount; ++i) {
                DruidConnectionHolder item = evictConnections[i];
                Connection connection = item.getConnection();
                JdbcUtils.close(connection);
                destroyCountUpdater.incrementAndGet(this);
            }
            Arrays.fill(evictConnections, null);
        }
        //对keepAliveConnections中的连接进行可用性检测,从而决定是否关闭
        if (keepAliveCount > 0) {
            this.getDataSourceStat().addKeepAliveCheckCount(keepAliveCount);
            // keep order
            for (int i = keepAliveCount - 1; i >= 0; --i) {
                DruidConnectionHolder holer = keepAliveConnections[i];
                Connection connection = holer.getConnection();
                holer.incrementKeepAliveCheckCount();

                boolean validate = false;
                try {
                    this.validateConnection(connection);
                    validate = true;
                } catch (Throwable error) {
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("keepAliveErr", error);
                    }
                    // skip
                }

                if (validate) {
                    holer.lastActiveTimeMillis = System.currentTimeMillis();
                    put(holer);
                } else {
                    JdbcUtils.close(connection);
                }
            }
            Arrays.fill(keepAliveConnections, null);
        }
    }

//removeAbandoned
 public int removeAbandoned() {
        int removeCount = 0;

        long currrentNanos = System.nanoTime();

        List<DruidPooledConnection> abandonedList = new ArrayList<DruidPooledConnection>();

        activeConnectionLock.lock();
        //回收超过removeAbandonedTimeout时间的连接,当然要配置removeAbandoned: true
        try {
            Iterator<DruidPooledConnection> iter = activeConnections.keySet().iterator();

            for (; iter.hasNext();) {
                DruidPooledConnection pooledConnection = iter.next();

                if (pooledConnection.isRunning()) {
                    continue;
                }

                long timeMillis = (currrentNanos - pooledConnection.getConnectedTimeNano()) / (1000 * 1000);

                if (timeMillis >= removeAbandonedTimeoutMillis) {
                    iter.remove();
                    pooledConnection.setTraceEnable(false);
                    abandonedList.add(pooledConnection);
                }
            }
        } finally {
            activeConnectionLock.unlock();
        }

        if (abandonedList.size() > 0) {
            for (DruidPooledConnection pooledConnection : abandonedList) {
                final ReentrantLock lock = pooledConnection.lock;
                lock.lock();
                try {
                    if (pooledConnection.isDisable()) {
                        continue;
                    }
                } finally {
                    lock.unlock();
                }

                JdbcUtils.close(pooledConnection);
                pooledConnection.abandond();
                removeAbandonedCount++;
                removeCount++;
                //打印回收日志,根据配置logAbandoned:true
                if (isLogAbandoned()) {
                    ......
                    LOG.error(buf.toString());
                }
            }
        }
        return removeCount;
    }

 初始化关键的就是这么多,其中也调起了创建连接的线程和回收连接的线程,它们各自进行着各自的工作。这里用到了ReentrantLock和CountDownLatch来控制同步。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值