vibur-dbcp 是一个并发、快速和功能齐全的 JDBC 连接池,提供先进的性能监控功能。本文主要介绍 vibur-dbcp 的基本使用,文中使用到的软件版本:Java 1.8.0_191、vibur-dbcp 25.0、Spring Boot 2.3.12.RELEASE。
1、配置参数
1.1、连接池大小及公平性配置
参数 |
类型 |
默认值 |
描述 |
poolInitialSize |
int |
5 |
初始连接数 |
poolMaxSize |
int |
50 |
最大连接数 |
poolFair |
boolean |
true |
如果为 true,保证线程按照先进先出的次序还获取连接 |
poolEnableConnectionTracking |
boolean |
false |
如果为 true,连接池会记录每个借出连接的堆栈信息 |
name |
String |
"p" + auto-generated id |
连接池名称 |
1.2、基础配置
参数 |
类型 |
默认值 |
描述 |
driver |
Driver |
null |
jdbc 的驱动;vibus 寻找驱动的次序: 1.driver 参数 2.driverClassName 参数 3.通过 jdbcUrl 来确定驱动
|
driverProperties |
Properties |
null |
驱动的参数,将被用来调用 Driver.connect() 方法 |
driverClassName |
String |
null |
驱动名称 |
jdbcUrl |
String |
|
jdbc 连接 url |
username |
String |
|
用户名 |
password |
String |
|
密码 |
externalDataSource |
DataSource |
null |
外部数据源,如果设置了将从该数据源获取连接 |
allowConnectionAfterTermination |
boolean |
false |
连接池中断后是否允许获取连接 |
allowUnwrapping |
boolean |
true |
是否允许获取 jdbc 的底层对象 |
1.3、连接超时及重试
参数 |
类型 |
默认值 |
描述 |
connectionTimeoutInMs |
long |
15000 |
获取连接(DataSource.getConnection())的超时时间;0 表示无限制 |
loginTimeoutInSeconds |
int |
5 |
创建连接的超时时间,该值将用于调用 DriverManager.setLoginTimeout() 方法 |
acquireRetryDelayInMs |
long |
500 |
创建连接失败时,等待重试的时间 |
acquireRetryAttempt |
int |
3 |
创建连接失败时,最大重试次数 |
1.4、连接校验
参数 |
类型 |
默认值 |
描述 |
connectionIdleLimitInSeconds |
int |
5 |
从连接池获取连接时,如果获取的连接空闲时间超过该设置,将对该连接进行校验。0 表示获取连接时每次都校验, 负数表示永远不校验。 |
validateTimeoutInSeconds |
int |
3 |
获取连接时执行 testConnectionQuery 的超时时间,或创建连接 执行 initSQL 的超时时间。 |
testConnectionQuery |
String |
isValid |
校验连接的查询语句,如果不设置则使用 Connection.isValid(int) 来校验连接;如果驱动支持 JDBC 4,强烈建议使用默认值,这会使得校验变得高效。 |
initSQL |
String |
null |
连接第一次创建时执行的查询语句;isValid 表示将执行 Connection.isValid(int) 方法。 |
useNetworkTimeout |
boolean |
false |
如果为 true,在 testConnectionQuery 或 initSQL 启用且不为 isValid 的情况下,在执行 testConnectionQuery 或 initSQL 时,将调用 Connection.setNetworkTimeout() 方法;需要保证驱动支持 Connection.setNetworkTimeout() 方法。 |
networkTimeoutExecutor |
Executor |
null |
useNetworkTimeout 启用时,执行 Connection.setNetworkTimeout(Executor executor, int milliseconds) 方法需要的 executor 对象。 |
1.5、查询慢及大结果集日志设置
参数 |
类型 |
默认值 |
描述 |
logQueryExecutionLongerThanMs |
long |
3000 |
对于长时间查询的语句是否记录日志;正数表示 SQL 语句的查询时间大于等于该设置时记录日志,0 表示总是记录,负数表示不记录 |
logStackTraceForLongQueryExecution |
boolean |
false |
如果为 true,在 logQueryExecutionLongerThanMs 启用并记录日志时,同时记录 SQL 语句的堆栈信息。 |
logLargeResultSet |
long |
500 |
对于大结果集是否记录日志;正数表示如果从结果集中获取的结果条数(ResultSet.next() 的执行次数)超过该设置,记录日志;负数表示不记录。 |
logStackTraceForLargeResultSet |
boolean |
false |
如果为 true,在 logLargeResultSet 启用并记录日志时,同时记录 SQL 语句的堆栈信息。 |
includeQueryParameters |
boolean |
true |
是否收集查询 SQL 的参数信息 |
1.6、获取连接慢及超时日志设置
参数 |
类型 |
默认值 |
描述 |
logConnectionLongerThanMs |
long |
3000 |
获取连接(DataSource.getConnection())的时间如果超过该设置,将记录日志;0 表示总是记录日志;负数表示不记录;如果 logConnectionLongerThanMs 大于 connectionTimeoutInMs,logConnectionLongerThanMs 将被设置为 connectionTimeoutInMs 的值。 |
logStackTraceForLongConnection |
boolean |
false |
如果为 true,在 logConnectionLongerThanMs 启动并记录日志时,同时记录获取连接的堆栈信息。 |
logTakenConnectionsOnTimeout |
boolean |
false |
从连接池获取连接超时,是否打印日志;如果为 true,超时了会大于所有借出连接的状态信息及堆栈信息。日志的格式可通过 takenConnectionsFormatter 设置。 |
logAllStackTracesOnTimeout |
boolean |
false |
如果为 true,在 logTakenConnectionsOnTimeout 启用并记录日志时,同时记录其他所有没有获取连接的线程的堆栈信息 |
logLineRegex |
Pattern |
null |
记录堆栈信息时(依据如下参数:logStackTraceForLongConnection, logStackTraceForLargeResultSet, logStackTraceForLongQueryExecution, logTakenConnectionsOnTimeout, logAllStackTracesOnTimeout),只记录符合正则表达式的信息。null 表示记录完整的堆栈信息。 |
takenConnectionsFormatter |
TakenConnectionsFormatter |
TakenConnectionsFormatter.Default |
logTakenConnectionsOnTimeout 启用并记录日志时,可通过该参数设置日志的格式。 |
1.7、回调函数
回调函数只能在配置阶段设置,且启动后不能修改。
函数 |
类型 |
默认值 |
描述 |
viburDS.getConnHooks().addOnInit(...) |
Hook.InitConnection |
null |
连接初始化后执行的函数 |
viburDS.getConnHooks().addOnGet(...) |
Hook.GetConnection |
null |
从连接池获取连接后执行的函数 |
viburDS.getConnHooks().addOnClose(...) |
Hook.CloseConnection |
null |
连接返回连接池前执行的函数 |
viburDS.getConnHooks().addOnDestroy(...) |
Hook.DestroyConnection |
null |
原始连接关闭后执行的函数 |
viburDS.getConnHooks().addOnTimeout(...) |
Hook.GetConnectionTimeout |
null |
在 logTakenConnectionsOnTimeout 启用并记录后执行的函数 |
viburDS.getInvocationHooks().addOnMethodInvocation(...) |
Hook.MethodInvocation |
null |
在执行 JDBC 接口方法前,执行该函数;继承 Object 的方法、有关 close 的方法、java.sql.Wrapper 执行时不执行该函数。 |
viburDS.getInvocationHooks().addOnStatementExecution(...) |
Hook.StatementExecution |
null |
在 JDBC Statement 执行时,该函数将包裹(around) Statement 的执行。 |
viburDS.getInvocationHooks().addOnResultSetRetrieval(...) |
Hook.ResultSetRetrieval |
null |
在结果集关闭后执行该方法。 |
1.8、连接默认行为设置
参数 |
类型 |
默认值 |
描述 |
clearSQLWarnings |
boolean |
false |
如果为 true,在连接返回连接池前,会清除 SQL 警告。 |
resetDefaultsAfterUse |
boolean |
false |
如果为 true,在连接返回连接池后,重置该连接。 |
defaultAutoCommit |
boolean |
Driver's default |
默认是否自动提交 |
defaultReadOnly |
boolean |
Driver's default |
默认是否只读 |
defaultTransactionIsolation |
String |
Driver's default |
默认的隔离级别 |
defaultCatalog |
String |
Driver's default |
默认的 catalog |
1.9、Statement 缓存设置
参数 |
类型 |
默认值 |
描述 |
statementCacheMaxSize |
int |
0 |
statement 缓存的最大数量;0 表示不启用 statement 缓存,最大不超过 2000。 |
1.10、连接池缩小设置
参数 |
类型 |
默认值 |
描述 |
poolReducerClass |
String |
org.vibur.dbcp.pool.PoolReducer |
管理连接池缩小的类 |
reducerTimeIntervalInSeconds |
int |
30 |
连接池中的空闲连接多长时间后,空闲连接的数量将被减少 |
reducerSamples |
int |
15 |
在 reducerTimeIntervalInSeconds 时间内,poolReducer 多长时间醒来以统计连接池的信息。 |
1.11、严重 SQL 状态
参数 |
类型 |
默认值 |
描述 |
criticalSQLStates |
String |
08001,08006,08007,08S01,57P01,57P02,57P03,JZ0C0,JZ0C1 |
如果一个 SQL 异常出现在该设置里,将会失效所有的连接并关闭连接池。 |
1.12、启用 JMX
参数 |
类型 |
默认值 |
描述 |
enableJMX |
boolean |
true |
是否开启 JMX |
详细说明可参考官网文档:http://www.vibur.org/
2、使用
2.1、直接使用
2.1.1、引入依赖
<dependency>
<groupId>org.vibur</groupId>
<artifactId>vibur-dbcp</artifactId>
<version>25.0</version>
</dependency>
<dependency>
<groupId>com.googlecode.concurrentlinkedhashmap</groupId>
<artifactId>concurrentlinkedhashmap-lru</artifactId>
<version>1.4.2</version>
</dependency>
2.1.2、使用例子
package com.abc.demo.general.dbpool;
import org.vibur.dbcp.ViburDBCPDataSource;
import java.sql.*;
public class ViburDbcpCase {
public static void main(String[] args) {
ViburDBCPDataSource viburDBCPDataSource = new ViburDBCPDataSource();
viburDBCPDataSource.setName("vibur-dbcp连接池");
viburDBCPDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
viburDBCPDataSource.setJdbcUrl("jdbc:mysql://10.40.9.11:3306/mydb?useUnicode=true&characterEncoding=UTF-8");
viburDBCPDataSource.setUsername("root");
viburDBCPDataSource.setPassword("123456");
viburDBCPDataSource.setPoolInitialSize(2);
viburDBCPDataSource.setPoolMaxSize(10);
viburDBCPDataSource.setConnectionIdleLimitInSeconds(30);
viburDBCPDataSource.setTestConnectionQuery("select 1");
viburDBCPDataSource.setLogQueryExecutionLongerThanMs(5000);
viburDBCPDataSource.setLogStackTraceForLongQueryExecution(true);
viburDBCPDataSource.setStatementCacheMaxSize(200);
viburDBCPDataSource.start();
Connection connection = null;
try {
connection = viburDBCPDataSource.getConnection();
Statement st = connection.createStatement();
ResultSet rs = st.executeQuery("select version()");
if (rs.next()) {
System.out.println(rs.getString(1));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
close(connection);
}
//实际使用中一般是在应用启动时初始化数据源,应用从数据源中获取连接;并不会关闭数据源。
viburDBCPDataSource.close();
}
private static void close(Connection connection) {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
2.2、在 SpringBoot 中使用
2.1.1、引入依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
<relativePath />
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.vibur</groupId>
<artifactId>vibur-dbcp</artifactId>
<version>25.0</version>
</dependency>
<dependency>
<groupId>com.googlecode.concurrentlinkedhashmap</groupId>
<artifactId>concurrentlinkedhashmap-lru</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
2.1.2、单数据源
application.yml 配置:
spring:
datasource:
vibur:
name: vibur-dbcp连接池
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://10.110.74.187:3306/egmp?useUnicode=true&characterEncoding=UTF-8
username: root
password: InsYR0ot187!
pool-initial-size: 2
pool-max-size: 10
connection-idle-limit-in-seconds: 30
test-connection-query: select 1
log-query-execution-longer-than-ms: 5000
log-stack-trace-for-long-query-execution: true
statement-cache-max-size: 200
数据源配置类:
package com.abc.demo.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.vibur.dbcp.ViburDBCPDataSource;
@Configuration
public class DataSourceConfig {
@Bean(name = "dataSource", initMethod = "start")
@ConfigurationProperties(prefix = "spring.datasource.vibur")
public ViburDBCPDataSource dataSource() {
ViburDBCPDataSource dataSource = DataSourceBuilder.create().type(ViburDBCPDataSource.class).build();
return dataSource;
}
}
使用:
@Autowired
private DataSource dataSource;
2.1.3、多数据源
application.yml 配置:
spring:
datasource:
vibur:
db1:
name: vibur-dbcp连接池1
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://10.110.74.187:3306/egmp?useUnicode=true&characterEncoding=UTF-8
username: root
password: InsYR0ot187!
pool-initial-size: 2
pool-max-size: 10
connection-idle-limit-in-seconds: 30
test-connection-query: select 1
log-query-execution-longer-than-ms: 5000
log-stack-trace-for-long-query-execution: true
statement-cache-max-size: 200
db2:
name: vibur-dbcp连接池2
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://10.110.74.187:3306/egmp?useUnicode=true&characterEncoding=UTF-8
username: root
password: InsYR0ot187!
pool-initial-size: 2
pool-max-size: 10
connection-idle-limit-in-seconds: 30
test-connection-query: select 1
log-query-execution-longer-than-ms: 5000
log-stack-trace-for-long-query-execution: true
statement-cache-max-size: 200
数据源配置类:
package com.abc.demo.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.vibur.dbcp.ViburDBCPDataSource;
@Configuration
public class DataSourceConfig {
@Primary
@Bean(name = "dataSource1", initMethod = "start")
@ConfigurationProperties("spring.datasource.vibur.db1")
public ViburDBCPDataSource dataSourceOne(){
return DataSourceBuilder.create().type(ViburDBCPDataSource.class).build();
}
@Bean(name = "dataSource2", initMethod = "start")
@ConfigurationProperties("spring.datasource.vibur.db2")
public ViburDBCPDataSource dataSourceTwo(){
return DataSourceBuilder.create().type(ViburDBCPDataSource.class).build();
}
}
使用:
@Autowired
@Qualifier("dataSource1")
private DataSource dataSource1;
@Autowired
@Qualifier("dataSource2")
private DataSource dataSource2;