Druid simple analysis connection pool initialization (a)

Druid Introduction :

Appear to solve the connection pool under high concurrency scenarios, each request for the performance overhead is created when a database connection program, and increase the response time of the request. Previously used C3P0 connection pool, and later the Druid concern connection pool, a division produced Alibaba database, known as the monitoring and raw database connection pool. Compared with other connection pool, it provides a rich, multi-dimensional data monitoring.

Druid git Source Address: github.com/alibaba/dru...

Druid initialization:

Common attributes noun Description:

url                            :数据库地址,通过前缀指定驱动类型。
username                       :数据库用户名
password                       :数据库密码
initialSize                    :连接池初始化大小
maxActive                      :连接池最大连接数
maxWait                        :获取连接最大等待时间
testOnBorrow                   :获取连接时是否检测连接是否有效
testOnReturn                   :回收连接时是否检测连接是否有效
testWhileIdle                  :获取连接时是否检测连接连接空闲时间超过
                                 timeBetweenEvictionRunsMillis,超过则检测连接
timeBetweenEvictionRunsMillis  :DestroyConnectionThread线程(定时检测连接有效性)
                                 执行间隔(Sleep控制)
minEvictableIdleTimeMillis     :连接再线程池中最小存活时间
removeAbandoned                :是否开启线程活动时间超过removeAbandonedTimeout,进行丢弃
removeAbandonedTimeout         :活动线程最大存活时间,超过直接丢弃(单位分钟)。
logAbandoned                   :关闭abandon连接是否打印日志。
filters                        :需要启用Druid的过滤器。
connectionInitSqls             :连接时需要设置的mysql参数,例:set names utf8mb4;asyncInit                      :是否异步初始化连接池
createScheduler                :初始化连接的线程池
validationQuery                :创建连接校验连接是否有效执行的sql语句
keepAlive                      :是否创建空闲连接
minIdle                        :最小空闲连接数
复制代码

Spring can be configured in the data source, and calls the init method directly init-method property.

<bean name="readDataSource1" class="com.alibaba.druid.pool.DruidDataSource"  
 init-method="init" destroy-method="close">复制代码

If you do not manually call initialization, when DataSource getConnection method of the first call will trigger the initialization logic to complete the initialization.

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);
    }
}复制代码

DruidDataSource initialization generally did a few things:

1. The process parameter value definition. The jdbcUrl type determination database (Mysql or the Oracle), to check if they are valid, initialized, and configured to load the filter driver.

2. Initialize the detector, such as is valid for the connection detector, and a query is valid the detector.

3. instantiate a data source statistics object JdbcDataSourceStat is the data storage center!JdbcDataSourceStat。Druid连接池以监控闻名,

4. Initialize three arrays, each storing a database connection, a dropped connection, still alive after connection has been detected, and initializes the database connection. Initialization three threads, threads are logging, generate a database connection, and the connection detecting whether a timeout.

DruidDataSource initialize a few key points:

Initialize the connection pool

if (createScheduler != null && asyncInit) {
    for (int i = 0; i < initialSize; ++i) {
        submitCreateTask(true);
    }
} else if (!asyncInit) {
    // init 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();
    }
}复制代码

When the property is configured createScheduler (thread pool), asyncInit (Boolean), and asyncInit true, the asynchronous initialization, the main thread on the contrary blocked until initialization is complete. poolingCount pool size for the current line.

private void submitCreateTask(boolean initTask) {
    createTaskCount++;
    //创建生成连接的Runnable任务
    CreateConnectionTask task = new CreateConnectionTask(initTask);
    if (createTasks == null) {
        //long类型数组用于存放Runnable任务
        createTasks = new long[8];
    }
    boolean putted = false;
    for (int i = 0; i < createTasks.length; ++i) {
        if (createTasks[i] == 0) {
            createTasks[i] = task.taskId;
            putted = true;
            break;
        }
    }
    if (!putted) {
        //当createTasks数组满时,扩容为之前数组大小的1.5倍。
        long[] array = new long[createTasks.length * 3 / 2];
        System.arraycopy(createTasks, 0, array, 0, createTasks.length);
        array[createTasks.length] = task.taskId;
        createTasks = array;
    }
    //丢进线程池执行
    this.createSchedulerFuture = createScheduler.submit(task);
}复制代码

Method createPhysicalConnection () returns a reference to the actual connection holds

PhysicalConnectionInfo objects, according to the configuration of the property, create a database connection. Initialize the connection (whether automatic commit, set the transaction isolation level after you've created, pre-execution
connectionInitSqls amount of data provided in the statement ), validation check is performed configured sql statement.

The DruidDataSource generated and returned PhysicalConnetionInfo 
DruidConnectionHolder object (Object Linking actual operation of the cell), the pool is connected into the array until the connection pool size equal initialSize.

If when asyncInit configured to false, the connection created through a while loop, the core code is as follows

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);
        }
    }
}复制代码

Consistent with the logic thread pool mode.


This completes the Druid thread pool, the conventional configuration and initialization parameters specified number of connections. There are three remaining threads created, leaving to the next chapter to continue the analysis


Note: Based on the level of restrictions, the document just for their own promotion, please advise discrepancies. (Ban on unauthorized transfer)


Guess you like

Origin juejin.im/post/5d67bd8ef265da03b5745ef6