Druid数据库连接池
Druid简介:
常用的数据库连接池:C3P0、DBCP、proxool、Druid
Druid的特点:
- 高性能。测试数据表明,Druid比DBCP、C3P0、BoneCP的性能都好很多
- 可以监控数据库访问性能,Druid内置提供了一个功能强大的StatFilter插件,能够详细统计SQL的执行性能,这对于线上分析数据库访问性能有帮助
- 可扩展性,提供基于Filter-Chain模式的扩展机制,Druid提供了一些内置的扩展机制,包括Stat、Log、Trace、HA等扩展。
- 替换DBCP,配置和DBCP兼容,可以方便替换DBCP。
- 适合大规模应用。结合Alibaba使用数据库连接池的经验,避免一些已知问题,例如数据库不可用恢复之后产生的连接风暴问题等。
Druid提供一个手工编写的高性能的方便扩展的SQL Parser。将会支持MySQL、Oracle等流行关系数据库的SQL Parser。
Parser组件包括如下几个部分:
- Lexer 词法解析
- Parser,Parser包括ExprParser,各种StatementParser。
- AST, Abstract Syntax Tree。ParserParse出来的结果就是AST。
- Visitor。对AST做各种处理,比如FormatOutput,遍历等等。
监控:
- Druid的统计信息定义代码实现在com/alibaba/druid/stat下。所有的Stat都全局静态变量的方式保存,这样做使得外部获取监控信息更容易。
- 获取Druid监控信息的入口是com.alibaba.druid.stat.JdbcStatManager
- Druid的监控统计信息都是通过StatFilter来实现的,如果你需要数据源进行监控,那你需要启用StatFilter
Subversion
http://code.alibabatech.com/svn/druid/trunk/
Download
Binary: http://code.alibabatech.com/mvn/releases/com/alibaba/druid/0.1.2/druid-0.1.2.jar
Source: http://code.alibabatech.com/mvn/releases/com/alibaba/druid/0.1.2/druid-0.1.2-sources.jar
Maven
Alibaba Open Source Repository
<repositories>
<repository>
<id>alibaba-opensource</id>
<name>alibaba-opensource</name>
<url>http://code.alibabatech.com/mvn/releases/</url>
<layout>default</layout>
</repository>
<repository>
<id>alibaba-opensource-snapshot</id>
<name>alibaba-opensource-snapshot</name>
<url>http://code.alibabatech.com/mvn/snapshots/</url>
<layout>default</layout>
</repository>
</repositories>
依赖配置
<dependencies> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>0.1.2</version> </dependency> </dependencies>
Druid应用:
druid的常用配置项如下:
|
配置 |
缺省值 |
说明 |
|
name |
|
配置这个属性的意义在于,如果存在多个数据源,监控的时候 |
|
jdbcUrl |
|
连接数据库的url,不同数据库不一样。例如: |
|
username |
|
连接数据库的用户名 |
|
password |
|
连接数据库的密码。如果你不希望密码直接写在配置文件中, |
|
driverClassName |
根据url自动识别 |
这一项可配可不配,如果不配置druid会根据url自动识别dbType, |
|
initialSize |
0 |
初始化时建立物理连接的个数。初始化发生在显示调用init方法, |
|
maxActive |
8 |
最大连接池数量 |
|
maxIdle |
8 |
已经不再使用,配置了也没效果 |
|
minIdle |
|
最小连接池数量 |
|
maxWait |
|
获取连接时最大等待时间,单位毫秒。配置了maxWait之后, |
|
poolPreparedStatements |
false |
是否缓存preparedStatement,也就是PSCache。 |
|
maxOpenPreparedStatements |
-1 |
要启用PSCache,必须配置大于0,当大于0时, |
|
validationQuery |
|
用来检测连接是否有效的sql,要求是一个查询语句。 |
|
testOnBorrow |
true |
申请连接时执行validationQuery检测连接是否有效, |
|
testOnReturn |
false |
归还连接时执行validationQuery检测连接是否有效, |
|
testWhileIdle |
false |
建议配置为true,不影响性能,并且保证安全性。 |
|
timeBetweenEvictionRunsMillis |
|
有两个含义: |
|
numTestsPerEvictionRun |
|
不再使用,一个DruidDataSource只支持一个EvictionRun |
|
minEvictableIdleTimeMillis |
|
Destory线程中如果检测到当前连接的最后活跃时间和当前时间的差值大于 |
|
connectionInitSqls |
|
物理连接初始化的时候执行的sql |
|
exceptionSorter |
根据dbType自动识别 |
当数据库抛出一些不可恢复的异常时,抛弃连接 |
|
filters |
|
属性类型是字符串,通过别名的方式配置扩展插件, |
|
proxyFilters |
|
类型是List<com.alibaba.druid.filter.Filter>, |
|
removeAbandoned |
|
对于建立时间超过removeAbandonedTimeout的连接强制关闭 |
|
removeAbandonedTimeout |
|
指定连接建立多长时间就需要被强制关闭 |
|
logAbandoned |
|
指定发生removeabandoned的时候,是否记录当前线程的堆栈信息到日志中 |
结合Spring配置数据库连接池:
url:jdbc:mysql://localhost:3306/dragoon_v25_masterdb driverClassName:com.mysql.jdbc.Driver username:root password:aaaaaaaa filters:stat maxActive:20 initialSize:1 maxWait:60000 minIdle:10 #maxIdle:15 timeBetweenEvictionRunsMillis:60000 minEvictableIdleTimeMillis:300000 validationQuery:SELECT 'x' testWhileIdle:true testOnBorrow:false testOnReturn:false #poolPreparedStatements:true maxOpenPreparedStatements:20 #禁用对于长时间不使用的连接强制关闭的功能 removeAbandoned:false #超过30分钟开始关闭空闲连接,由于removeAbandoned为false,这个设置项不再起作用 removeAbandonedTimeout:1800 #将当前关闭动作记录到日志,由于removeAbandoned为false,这个设置项不再起作用 logAbandoned:true
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!-- 给web使用的spring文件 --> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>/WEB-INF/classes/dbconfig.properties</value> </list> </property> </bean> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> <property name="driverClassName" value="${driverClassName}" /> <property name="filters" value="${filters}" /> <property name="maxActive" value="${maxActive}" /> <property name="initialSize" value="${initialSize}" /> <property name="maxWait" value="${maxWait}" /> <property name="minIdle" value="${minIdle}" /> <property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}" /> <property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis}" /> <property name="validationQuery" value="${validationQuery}" /> <property name="testWhileIdle" value="${testWhileIdle}" /> <property name="testOnBorrow" value="${testOnBorrow}" /> <property name="testOnReturn" value="${testOnReturn}" /> <property name="maxOpenPreparedStatements" value="${maxOpenPreparedStatements}" /> <property name="removeAbandoned" value="${removeAbandoned}" /> <!-- 打开removeAbandoned功能 --> <property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" /> <!-- 1800秒,也就是30分钟 --> <property name="logAbandoned" value="${logAbandoned}" /> <!-- 关闭abanded连接时输出错误日志 --> </bean> <bean id="dataSourceDbcp" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${driverClassName}" /> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> <property name="maxActive" value="${maxActive}" /> <property name="minIdle" value="${minIdle}" /> <property name="maxWait" value="${maxWait}" /> <property name="defaultAutoCommit" value="true" /> <property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}" /> <property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis}" /> <property name="validationQuery" value="${validationQuery}" /> <property name="testWhileIdle" value="${testWhileIdle}" /> <property name="testOnBorrow" value="${testOnBorrow}" /> <property name="testOnReturn" value="${testOnReturn}" /> <property name="maxOpenPreparedStatements" value="${maxOpenPreparedStatements}" /> <property name="removeAbandoned" value="${removeAbandoned}" /> <property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" /> <property name="logAbandoned" value="${logAbandoned}" /> </bean> <!-- jdbcTemplate --> <bean id="jdbc" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource"> <ref bean="dataSource" /> </property> </bean> </beans>
配置项中指定了各个参数后,在连接池内部是这么使用这些参数的。数据库连接池在初始化的时候会创建initialSize个连接,当有数据库操作时,会从池中取出一个连接。如果当前池中正在使用的连接数等于maxActive,则会等待一段时间,等待其他操作释放掉某一个连接,如果这个等待时间超过了maxWait,则会报错;如果当前正在使用的连接数没有达到maxActive,则判断当前是否空闲连接,如果有则直接使用空闲连接,如果没有则新建立一个连接。在连接使用完毕后,不是将其物理连接关闭,而是将其放入池中等待其他操作复用。
同时连接池内部有机制判断,如果当前的总的连接数少于miniIdle,则会建立新的空闲连接,以保证连接数得到miniIdle。如果当前连接池中某个连接在空闲了timeBetweenEvictionRunsMillis时间后任然没有使用,则被物理性的关闭掉。有些数据库连接的时候有超时限制(mysql连接在8小时后断开),或者由于网络中断等原因,连接池的连接会出现失效的情况,这时候可以设置一个testWhileIdle参数为true,注意这里的“while”这个单词应该翻译成“如果”,换句话说testWhileIdle写为testIfIdle更好理解些,其含义为连接在获取连接的时候,如果检测到当前连接不活跃的时间超过了timeBetweenEvictionRunsMillis,则去手动检测一下当前连接的有效性,在保证确实有效后才加以使用。在检测活跃性时,如果当前的活跃时间大于minEvictableIdleTimeMillis,则认为需要关闭当前连接。当然,为了保证绝对的可用性,你也可以使用testOnBorrow为true(即在每次获取Connection对象时都检测其可用性),不过这样会影响性能。
最后说一下removeAbandoned参数,其实druid是不能检测到当前使用的连接是否发生了连接泄露,所以在代码内部就假定如果一个连接建立连接的时间很长,则将其认定为泄露,继而强制将其关闭掉。这个参数在druid中默认是不开启的,github上给出的wiki中也对其没有丝毫提及。其实在代码中设置testWhileIdle就能在一定程序上消灭掉泄露的连接,因为如果发生了泄露,那么他的不活跃时间肯定会在某个时间点大于timeBetweenEvictionRunsMillis,继而被回收掉。
web监控:
web.xml配置如下:
<servlet> <servlet-name>DruidStatView</servlet-name> <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>DruidStatView</servlet-name> <url-pattern>/druid/*</url-pattern> </servlet-mapping>
打开http://localhost:8080/druid/index.html,会看到监控界面,点击其中的sql标签。

浙公网安备 33010602011771号