Tomcat JDBC连接池(Tomcat 9)
通用配置项
配置项 | 描述 |
---|---|
factory | 必需,且值需要是org.apache.tomcat.jdbc.pool.DataSourceFactory 表示使用Tomcat JDBC连接池 |
type | 指定创建的数据源类型,只能是javax.sql.DataSource 或javax.sql.XADataSource 之一 |
defaultAutoCommit | (boolean )该数据源创建的连接的默认自动提交属性,如果没有设置,不会调用Connection#setAutoCommit ,连接的自动提交属性取决于底层的数据库驱动 |
defaultReadOnly | (boolean )该数据源创建的连接的默认只读属性,如果没有设置,不会调用Connection#setReadOnly ,连接的默认只读属性取决于底层的数据库驱动,注意有的驱动不支持只读模式,如Informix |
defaultTransactionIsolation | (String ) 该连接池床架你的连接的默认事务隔离级别,取值为如下的可选值之一:NONE 、READ_COMMITTED 、READ_UNCOMMITTED 、REPEATABLE_READ 、SERIALIZABLE 。如果没有设置,连接的默认事务隔离级别取决于数据库驱动 |
defaultCatalog | (String ) The default catalog of connections created by this pool. |
driverClassName | (String ) 使用的JDBC驱动类的全类名,驱动类需要是加载tomcat-jdbc.jar的类加载器可以获取的. 如:oracle.jdbc.OracleDriver 和com.mysql.cj.jdbc.Driver (MySQL 8)和com.mysql.jdbc.Driver (MySQL 8以前) |
username | 用户名 |
password | 密码 |
maxActive | (int )最大连接数,默认100
|
maxIdle | (int )最大空闲连接数,默认为maxActive:100 |
minIdle | (int )最小空闲连接数,默认为initialSize:10 |
initialSize | (int )连接池创建时的初始连接数,默认:10 |
maxWait | (int )从该连接池中等待获取连接的超时上限,单位:毫秒,默认:30000(30秒),获取连接超时连接池将抛出异常 |
testOnBorrow | (boolean )每次获取连接时是否检测连接有效性,失效的连接将被连接池丢弃,默认为false
|
testOnConnect | (boolean ) 创建连接时测试连接的有效性,验证失败时抛出SQLException ,默认为false
|
testOnReturn | (boolean )每次归还连接的时候是否检测连接的有效性,默认为false
|
testWhileIdle | 是否开启空闲清理线程,默认为false ,一旦开启,连接池将会定期检测空闲连接 |
validationQuery | 验证连接使用的SQL,Oracle为select 1 from dual , MySQL为select 1
|
validationQueryTimeout | 验证SQL的执行超时上限,单位:秒,为负数表示关闭连接验证超时,默认-1
|
validatorClassName | (String ) 实现 org.apache.tomcat.jdbc.pool.Validator 接口并提供无参构造方法的实现类,用来替代连接验证SQL,对连接进行验证。默认为null ,示例如:com.mycompany.project.SimpleValidator
|
timeBetweenEvictionRunsMillis | (int ) 空闲连接清理线程运行的间隔时间,单位:毫秒。该值应该大于1秒,默认5000(5秒) |
minEvictableIdleTimeMillis | (int ) 连接被回收前可以空闲的最小时间,单位:毫秒。默认值:60000(60秒) |
removeAbandoned | (boolean ) 是否移除抛弃的(abandoned)连接,一个连接使用超过了removeAbandonedTimeout 上限就被视为抛弃的,开启该开关可以恢复那些应用没有关闭的连接。默认为false
|
removeAbandonedTimeout | (int ) 单位:秒,一个连接使用超过多久就视为抛弃的(abandoned),默认为60 秒(60 seconds). 该值应该超过你的应用中最长的SQL可能运行的时间 |
logAbandoned | (boolean ) 记录抛弃连接的应用的堆栈信息,默认false ,会增加系统开销,因为为了能够在可能发生的连接被抛弃时记录堆栈 ,应用每次获取连接时都需要生成堆栈信息 |
connectionProperties | (String ) 创建新的连接时传给JDBC驱动的连接属性,格式必须是[propertyName=property;]* ,注意user 和password 参数会被显式传递,因此无需再这里再次指定,默认为null
|
accessToUnderlyingConnectionAllowed | tomcat-jdbc未使用 |
numTestsPerEvictionRun | tomcat-jdbc未使用 |
poolPreparedStatements | tomcat-jdbc未使用 |
maxOpenPreparedStatements | tomcat-jdbc未使用 |
连接检查相关选项
连接检查检查连接的有效性,清理失效的连接
- validationQuery:连接检查时使用的SQL,注意不同的数据库不同,详见上表。
- validationQueryTimeout:执行连接检查的语句的超时时间(秒),默认
-1
表示无限等待; - testOnConnect:每次创建连接时测试连接有效性,验证失败抛出
SQLException
; - testOnBorrow:每次从连接池借出连接时是否检查连接可用性;
- testOnReturn:每次归还连接时是否检测连接有效性。
注意:
testOnBorrow
并不适合高负载的系统,将会导致每次获取连接都增加一次查询请求,带来额外负载。
高负载系统可以考虑使用testWhileIdle
,在空闲时检测连接;
testOnReturn
一般用处不大。
清理线程相关选项
- testWhileIdle:是否开启连接连接清理线程,连接清理线程使用
validationQuery
验证连接池中的空闲连接,丢弃未通过测试的连接。 - timeBetweenEvictionRunsMillis:evictor两次运行的间隔时间(毫秒)
- minEvictableIdleTimeMillis:连接被回收前可以空闲的最短时间,单位:毫秒。默认值:60000(60秒)
当启动evictor线程后,如果连接数小于minIdle
,则创建新的连接直到minIdle
个数,没有启动evictor线程时,minIdle
没有意义;
无论是否开启evictor线程,当业务压力增加时,活跃连接数可能超过maxIdle
,但不会超过maxActive
;活跃连接数超过maxIdle
时,使用完的活跃连接归还时会立即关闭;
在没有开启evictor线程,假设活跃连接个数曾经超过maxIdle
接近或达到maxActive
,当压力变小,使用中的连接数降低时,假设最终所有连接都空闲下来时,这时空闲连接将维持在maxIdle
因为此时没有evictor线程。
开启evictor线程后,上述的场景,evictor线程每隔timeBetweenEvictionRunsMillis
检测空闲,如果连接空闲超过minEvictableIdleTimeMillis
,则清理空闲连接,最终使空闲连接维持在minIdle
。
可见当maxActive
大于maxIdle
时,活跃连接超过maxIdle
后归还就会被关闭,再获取时如果没有可用连接,总连接数又小于maxActive
时,又会新建连接,因此这种情况会带来连接池伸缩造成的性能开销,因此推荐配置maxActive
等于maxIdle
避免连接池伸缩开销。
initialSize
是在连接池创建时的初始连接个数,如果启动evictor且initialSize
小于minIdle
,则evictor会创建空闲连接将连接数维持在minIdle
;如果没有开启evictor,则只有连接使用请求上升时,才会在initialSize
基础上创建新的连接。
Abandoned连接选项
Abandoned连接指应用长时间未归还给连接池的连接,连接池可以自动关闭这些连接,以防止连接泄漏。相关配置项如下,具体释义见上表。
- removeAbandoned
- removeAbandonedTimeout
- logAbandoned
注意对于长时间使用同一连接进行批量操作的场景可能不适用该功能。
removeAbandonedTimeout
必须长于应用可能的最长SQL执行时间,否则SQL尚未完成执行,连接就被关闭,因此长时间使用同一连接进行批量操作的场景应谨慎使用该功能。
系统配置项
配置项 | 含义 |
---|---|
org.apache.tomcat.jdbc.pool.onlyAttemptCurrentClassLoader |
Tomcat JDBC 增强配置项
配置项 | 含义 |
---|---|
initSQL | |
jdbcInterceptors | |
validationInterval | |
jmxEnabled | |
fairQueue | |
abandonWhenPercentageFull | |
maxAge | |
useEquals | |
suspectTimeout | |
rollbackOnReturn | |
commitOnReturn | |
alternateUsernameAllowed | |
dataSource | |
dataSourceJNDI | |
useDisposableConnectionFacade | |
logValidationErrors | |
propagateInterruptState | |
ignoreExceptionOnPreLoad | |
useStatementFacade |
Spring Boot中使用Tomcat JDBC连接池
基于Spring Boot 2.x,直接将tomcat-jdbc加入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<exclusions>
<exclusion>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
</dependency>
在应用中使用配置类创建DataSource
类型的Bean:
@Bean
@ConfigurationProperties("your.datasource.prefix")
public DataSource dataSource() {
return DataSourceBuilder.create().type(org.apache.tomcat.jdbc.pool.DataSource.class).build();
}
Spring Boot使用Tomcat JDBC作为Tomcat JNDI连接池
Tomcat中也带有Tomcat JDBC的jar,但是默认TOMCAT JNDI使用DBCP连接池,如果使用Tomcat JDBC作为Tomcat JNDI的连接池实现,那么就必须在配置中显式指定factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
。
在Tomcat安装目录下的conf/
目录中增加context.xml
文件:
<?xml version='1.0' encoding='utf-8'?>
<Context useHttpOnly="true" privileged="true" reloadable="true">
<Resource name="jdbc/TestDB"
auth="Container"
type="javax.sql.DataSource"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
testWhileIdle="true"
testOnBorrow="true"
testOnReturn="false"
validationQuery="SELECT 1"
validationInterval="30000"
timeBetweenEvictionRunsMillis="30000"
maxActive="100"
minIdle="10"
maxWait="10000"
initialSize="10"
removeAbandonedTimeout="60"
removeAbandoned="true"
logAbandoned="true"
minEvictableIdleTimeMillis="30000"
jmxEnabled="true"
jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;
org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"
username="root"
password="password"
driverClassName="com.mysql.cj.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mysql"
/>
</Context>
在配置类中通过JNDI查询获取相应的DataSource
实例:
@Bean
public DataSource jndiDataSource() {
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
DataSource dataSource = dataSourceLookup.getDataSource("jdbc/TestDB");
return dataSource;
}
连接Oracle 12c:
- 驱动
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
</dependency>
- 驱动类
oracle.jcbc.OracleDriver
- 连接串:
jdbc:oracle:thin:@IP:PORT:SID
- 连接验证SQL:
select 1 from dual
连接MySQL 8
- 驱动
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
</dependency>
- 驱动类
com.mysql.cj.jdbc.Driver
- 连接串:
jdbc:mysql://IP:PORT/DB_NAME
- 连接验证SQL:
select 1