聊聊druid连接池的参数配置

2023-09-28 08:55:03 浏览数 (2)

本文主要研究一下druid连接池的参数配置

DruidDataSourceFactory

druid-1.2.11-sources.jar!/com/alibaba/druid/pool/DruidDataSourceFactory.java

代码语言:javascript复制
public class DruidDataSourceFactory implements ObjectFactory {
    private static final Log LOG = LogFactory.getLog(DruidDataSourceFactory.class);

    static final int UNKNOWN_TRANSACTIONISOLATION = -1;

    public static final String PROP_DEFAULTAUTOCOMMIT = "defaultAutoCommit";
    public static final String PROP_DEFAULTREADONLY = "defaultReadOnly";
    public static final String PROP_DEFAULTTRANSACTIONISOLATION = "defaultTransactionIsolation";
    public static final String PROP_DEFAULTCATALOG = "defaultCatalog";
    public static final String PROP_DRIVERCLASSNAME = "driverClassName";
    public static final String PROP_MAXACTIVE = "maxActive";
    public static final String PROP_MAXIDLE = "maxIdle";
    public static final String PROP_MINIDLE = "minIdle";
    public static final String PROP_INITIALSIZE = "initialSize";
    public static final String PROP_MAXWAIT = "maxWait";
    public static final String PROP_TESTONBORROW = "testOnBorrow";
    public static final String PROP_TESTONRETURN = "testOnReturn";
    public static final String PROP_TIMEBETWEENEVICTIONRUNSMILLIS = "timeBetweenEvictionRunsMillis";
    public static final String PROP_NUMTESTSPEREVICTIONRUN = "numTestsPerEvictionRun";
    public static final String PROP_MINEVICTABLEIDLETIMEMILLIS = "minEvictableIdleTimeMillis";
    public static final String PROP_PHY_TIMEOUT_MILLIS = "phyTimeoutMillis";
    public static final String PROP_TESTWHILEIDLE = "testWhileIdle";
    public static final String PROP_PASSWORD = "password";
    public static final String PROP_URL = "url";
    public static final String PROP_USERNAME = "username";
    public static final String PROP_VALIDATIONQUERY = "validationQuery";
    public static final String PROP_VALIDATIONQUERY_TIMEOUT = "validationQueryTimeout";
    public static final String PROP_INITCONNECTIONSQLS = "initConnectionSqls";
    public static final String PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED = "accessToUnderlyingConnectionAllowed";
    public static final String PROP_REMOVEABANDONED = "removeAbandoned";
    public static final String PROP_REMOVEABANDONEDTIMEOUT = "removeAbandonedTimeout";
    public static final String PROP_LOGABANDONED = "logAbandoned";
    public static final String PROP_POOLPREPAREDSTATEMENTS = "poolPreparedStatements";
    public static final String PROP_MAXOPENPREPAREDSTATEMENTS = "maxOpenPreparedStatements";
    public static final String PROP_CONNECTIONPROPERTIES = "connectionProperties";
    public static final String PROP_FILTERS = "filters";
    public static final String PROP_EXCEPTION_SORTER = "exceptionSorter";
    public static final String PROP_EXCEPTION_SORTER_CLASS_NAME = "exception-sorter-class-name";
    public static final String PROP_NAME = "name";
    public static final String PROP_INIT = "init";

    private static final String[] ALL_PROPERTIES = {
            PROP_DEFAULTAUTOCOMMIT,
            PROP_DEFAULTREADONLY,
            PROP_DEFAULTTRANSACTIONISOLATION,
            PROP_DEFAULTCATALOG,
            PROP_DRIVERCLASSNAME,
            PROP_MAXACTIVE,
            PROP_MAXIDLE,
            PROP_MINIDLE,
            PROP_INITIALSIZE,
            PROP_MAXWAIT,
            PROP_TESTONBORROW,
            PROP_TESTONRETURN,
            PROP_TIMEBETWEENEVICTIONRUNSMILLIS,
            PROP_NUMTESTSPEREVICTIONRUN,
            PROP_MINEVICTABLEIDLETIMEMILLIS,
            PROP_TESTWHILEIDLE,
            PROP_PASSWORD,
            PROP_FILTERS,
            PROP_URL,
            PROP_USERNAME,
            PROP_VALIDATIONQUERY,
            PROP_VALIDATIONQUERY_TIMEOUT,
            PROP_INITCONNECTIONSQLS,
            PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED,
            PROP_REMOVEABANDONED,
            PROP_REMOVEABANDONEDTIMEOUT,
            PROP_LOGABANDONED,
            PROP_POOLPREPAREDSTATEMENTS,
            PROP_MAXOPENPREPAREDSTATEMENTS,
            PROP_CONNECTIONPROPERTIES,
            PROP_EXCEPTION_SORTER,
            PROP_EXCEPTION_SORTER_CLASS_NAME,
            PROP_INIT,
            PROP_NAME,

            "druid.timeBetweenLogStatsMillis",
            "druid.stat.sql.MaxSize",
            "druid.clearFiltersEnable",
            "druid.resetStatEnable", //
            "druid.notFullTimeoutRetryCount", //
            "druid.maxWaitThreadCount", //
            "druid.failFast", //
            "druid.phyTimeoutMillis", //
            "druid.wall.tenantColumn", //
            "druid.wall.updateAllow", //
            "druid.wall.deleteAllow", //
            "druid.wall.insertAllow", //
            "druid.wall.selelctAllow", //
            "druid.wall.multiStatementAllow", //
    };

    //......
}    

DruidDataSourceFactory的ALL_PROPERTIES常量定义了所有支持的可配置项

DruidDataSourceWrapper

com/alibaba/druid/spring/boot/autoconfigure/DruidDataSourceWrapper.java

代码语言:javascript复制
@ConfigurationProperties("spring.datasource.druid")
public class DruidDataSourceWrapper extends DruidDataSource implements InitializingBean {
    @Autowired
    private DataSourceProperties basicProperties;

    @Override
    public void afterPropertiesSet() throws Exception {
        //if not found prefix 'spring.datasource.druid' jdbc properties ,'spring.datasource' prefix jdbc properties will be used.
        if (super.getUsername() == null) {
            super.setUsername(basicProperties.determineUsername());
        }
        if (super.getPassword() == null) {
            super.setPassword(basicProperties.determinePassword());
        }
        if (super.getUrl() == null) {
            super.setUrl(basicProperties.determineUrl());
        }
        if (super.getDriverClassName() == null) {
            super.setDriverClassName(basicProperties.getDriverClassName());
        }
    }

    @Autowired(required = false)
    public void autoAddFilters(List<Filter> filters){
        super.filters.addAll(filters);
    }

    /**
     * Ignore the 'maxEvictableIdleTimeMillis &lt; minEvictableIdleTimeMillis' validate,
     * it will be validated again in {@link DruidDataSource#init()}.
     *
     * for fix issue #3084, #2763
     *
     * @since 1.1.14
     */
    @Override
    public void setMaxEvictableIdleTimeMillis(long maxEvictableIdleTimeMillis) {
        try {
            super.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis);
        } catch (IllegalArgumentException ignore) {
            super.maxEvictableIdleTimeMillis = maxEvictableIdleTimeMillis;
        }
    }
}

DruidDataSourceWrapper继承了DruidDataSource,在afterPropertiesSet的时候会使用DataSourceProperties的username、password、url、driverClassName,其他配置在DruidDataSource中

DruidDataSource

com/alibaba/druid/pool/DruidDataSource.java

代码语言:javascript复制
public class DruidDataSource extends DruidAbstractDataSource implements DruidDataSourceMBean, ManagedDataSource, Referenceable, Closeable, Cloneable, ConnectionPoolDataSource, MBeanRegistration {

	private boolean                          useGlobalDataSourceStat   = false;
    private boolean                          logDifferentThread        = true;
    private volatile boolean                 keepAlive                 = false;
    private boolean                          asyncInit                 = false;
    protected boolean                        killWhenSocketReadTimeout = false;
    protected boolean                        checkExecuteTime          = false;        
}

DruidDataSource继承了DruidAbstractDataSource,它只定义了keepAlive、asyncInit等几个配置,其它大部分配置在DruidAbstractDataSource中

DruidAbstractDataSource

com/alibaba/druid/pool/DruidAbstractDataSource.java

代码语言:javascript复制
public abstract class DruidAbstractDataSource extends WrapperAdapter implements DruidAbstractDataSourceMBean, DataSource, DataSourceProxy, Serializable {
    protected volatile int initialSize = DEFAULT_INITIAL_SIZE;
    public static final int DEFAULT_INITIAL_SIZE = 0;

    protected volatile int maxActive = DEFAULT_MAX_ACTIVE_SIZE;
    public static final int DEFAULT_MAX_ACTIVE_SIZE = 8;

    protected volatile int minIdle = DEFAULT_MIN_IDLE;
    public static final int DEFAULT_MIN_IDLE = 0;

    protected volatile int maxIdle = DEFAULT_MAX_IDLE;
    public static final int DEFAULT_MAX_IDLE = 8;

    protected volatile long maxWait = DEFAULT_MAX_WAIT;
    public static final int DEFAULT_MAX_WAIT = -1;

    protected volatile String validationQuery = DEFAULT_VALIDATION_QUERY;
    public static final String DEFAULT_VALIDATION_QUERY = null;   

    protected volatile int validationQueryTimeout = -1;

    protected volatile boolean testOnBorrow = DEFAULT_TEST_ON_BORROW;
    public static final boolean DEFAULT_TEST_ON_BORROW = false;

    protected volatile boolean testOnReturn = DEFAULT_TEST_ON_RETURN;
    public static final boolean DEFAULT_TEST_ON_RETURN = false;

    protected volatile boolean testWhileIdle = DEFAULT_WHILE_IDLE;
    public static final boolean DEFAULT_WHILE_IDLE = true;

    protected volatile int maxPoolPreparedStatementPerConnectionSize = 10;

    protected volatile long timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
    public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = 60 * 1000L;

    protected volatile int numTestsPerEvictionRun = DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
    public static final int DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3;

    protected volatile long minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
    public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L;

    protected volatile long maxEvictableIdleTimeMillis = DEFAULT_MAX_EVICTABLE_IDLE_TIME_MILLIS;
    public static final long DEFAULT_MAX_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 60L * 7;

    protected volatile long keepAliveBetweenTimeMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS * 2;

    protected volatile long phyTimeoutMillis = DEFAULT_PHY_TIMEOUT_MILLIS;
    public static final long DEFAULT_PHY_TIMEOUT_MILLIS = -1;

    protected volatile long timeBetweenConnectErrorMillis = DEFAULT_TIME_BETWEEN_CONNECT_ERROR_MILLIS;
    public static final long DEFAULT_TIME_BETWEEN_CONNECT_ERROR_MILLIS = 500;

}

DruidAbstractDataSource定义的配置及其默认值如下

类别

配置项

默认值

说明

数量

initialSize

0

-

数量

maxActive

8

-

数量

minIdle

0

-

数量

maxIdle

8

-

数量

maxPoolPreparedStatementPerConnectionSize

10

-

健康检测

validationQuery

null

mysql默认为SELECT 1

健康检测

validationQueryTimeout

-1

单位秒,mysql默认1s

健康检测

testOnBorrow

false

-

健康检测

testOnReturn

false

-

健康检测

testOnReturn

false

-

健康检测

testWhileIdle

true

-

evict

timeBetweenEvictionRunsMillis

60s

-

evict

numTestsPerEvictionRun

3

-

evict

minEvictableIdleTimeMillis

30分钟

-

evict

maxEvictableIdleTimeMillis

7小时

-

超时

maxWait

-1

单位毫秒

超时

keepAliveBetweenTimeMillis

120s

2* DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS

超时

phyTimeoutMillis

-1

-

超时

queryTimeout

0

-

超时

transactionQueryTimeout

0

-

错误

timeBetweenConnectErrorMillis

500ms

-

连接泄露

removeAbandoned

false

-

连接泄露

removeAbandonedTimeoutMillis

300s

-

获取连接时,若maxWait大于0则走的pollLast(nanos),其中maxWait是作为notEmpty.awaitNanos参数,毫秒转为nacos,若为负数则取0;若maxWait小于等于0则走的takeLast,执行的是notEmpty.await(),即阻塞等待

小结

druid连接池的配置主要是在DruidDataSource中,而DruidDataSource继承了DruidAbstractDataSource,它只定义了keepAlive、asyncInit等几个配置,其它大部分配置在DruidAbstractDataSource中,没有单独的一个配置类,然后默认只开启了testWhileIdle,maxWait默认为-1;因而建议强制配置maxWait为正数(单位毫秒);在并发量比较大的场景,若要保证连接池的稳定数量则可以将minIdle配置为与maxIdle一样。

0 人点赞