tomcat jdbc连接池详解之初始化

2022-03-28 20:07:15 浏览数 (1)

本文将从源码出发详解tomcat jdbc连接池的初始化过程,看下连接池初始化到底做了些什么

代码语言:javascript复制
    //创建连接池
     public ConnectionPool(PoolConfiguration prop) throws SQLException {
        //初始化连接池
        init(prop);
    }


        protected void init(PoolConfiguration properties) throws SQLException {
        poolProperties = properties;

        //校验连接池配置参数
        checkPoolConfiguration(properties);

        //make space for 10 extra in case we flow over a bit
        busy = new LinkedBlockingQueue<>();
        //busy = new FairBlockingQueue<PooledConnection>();
        //make space for 10 extra in case we flow over a bit
        if (properties.isFairQueue()) {
            idle = new FairBlockingQueue<>();
            //idle = new MultiLockFairBlockingQueue<PooledConnection>();
            //idle = new LinkedTransferQueue<PooledConnection>();
            //idle = new ArrayBlockingQueue<PooledConnection>(properties.getMaxActive(),false);
        } else {
            idle = new LinkedBlockingQueue<>();
        }

        //初始化PoolCleaner,该类是一个TimerTask,在定期任务内会执行checkAbandoned、checkIdle、testAllIdle等任务,详情可以参考https://mp.csdn.net/postedit/99671525
        initializePoolCleaner(properties);

        //create JMX MBean
        if (this.getPoolProperties().isJmxEnabled()) createMBean();

        //Parse and create an initial set of interceptors. Letting them know the pool has started.
        //These interceptors will not get any connection.
        PoolProperties.InterceptorDefinition[] proxies = getPoolProperties().getJdbcInterceptorsAsArray();
        for (int i=0; i<proxies.length; i  ) {
            try {
                if (log.isDebugEnabled()) {
                    log.debug("Creating interceptor instance of class:" proxies[i].getInterceptorClass());
                }
                JdbcInterceptor interceptor = proxies[i].getInterceptorClass().newInstance();
                interceptor.setProperties(proxies[i].getProperties());
                interceptor.poolStarted(this);
            }catch (Exception x) {
                log.error("Unable to inform interceptor of pool start.",x);
                if (jmxPool!=null) jmxPool.notify(org.apache.tomcat.jdbc.pool.jmx.ConnectionPool.NOTIFY_INIT, getStackTrace(x));
                close(true);
                SQLException ex = new SQLException();
                ex.initCause(x);
                throw ex;
            }
        }

        //用initialSize初始化线程池
        PooledConnection[] initialPool = new PooledConnection[poolProperties.getInitialSize()];
        try {
            for (int i = 0; i < initialPool.length; i  ) {
                //创建连接,创建的连接会被加入到busy队列
                initialPool[i] = this.borrowConnection(0, null, null); //don't wait, should be no contention
            } //for

        } catch (SQLException x) {
            log.error("Unable to create initial connections of pool.", x);
            if (!poolProperties.isIgnoreExceptionOnPreLoad()) {
                if (jmxPool!=null) jmxPool.notify(org.apache.tomcat.jdbc.pool.jmx.ConnectionPool.NOTIFY_INIT, getStackTrace(x));
                close(true);
                throw x;
            }
        } finally {
            //返回创建的初始化连接到idle队列中
            for (int i = 0; i < initialPool.length; i  ) {
                if (initialPool[i] != null) {
                    try {this.returnConnection(initialPool[i]);}catch(Exception x){/*NOOP*/}
                } //end if
            } //for
        } //catch

        closed = false;
    }

如上述代码所示tomcat jdbc连接池初始化做了以下工作:

1.检查连接池配置属性

2.初始化连接池任务(创建PoolCleaner)

3、根据initialSize创建PoolConnection数组,然后放入到idle队列中,这样从连接池获取数据库连接的时候就可以先使用idle队列中连接,如果idle连接没有可用连接则会判断当前连接池大小是否超过连接池配置的maxActive,如果没有则创建新的数据库连接,否则就会阻塞等待获取到连接为止(当前不是无条件等待,会有一个超时时间-根据连接池maxWait来定)!

0 人点赞