数据库连接池druid 的使用

来源:互联网 发布:木头马尾原创服装淘宝 编辑:程序博客网 时间:2024/04/30 19:21

Druid概述

DRUID是阿里巴巴开源平台上一个数据库连接池实现,它结合了C3P0、DBCP、PROXOOL等DB池的优点,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况,可以说是针对监控而生的DB连接池(据说是目前最好的连接池,不知道速度有没有BoneCP快)。


Druid一些常用的配置参数

和其它连接池一样DRUID的DataSource类为:com.alibaba.druid.pool.DruidDataSource,基本配置参数如下:

配置缺省值说明name 配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过名字来区分开来。 
如果没有配置,将会生成一个名字,格式是:"DataSource-" + System.identityHashCode(this)jdbcUrl 连接数据库的url,不同数据库不一样。例如: 
mysql : jdbc:mysql://10.20.153.104:3306/druid2 
oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnautousername 连接数据库的用户名password 连接数据库的密码。如果你不希望密码直接写在配置文件中,可以使用ConfigFilter。详细看这里:https://github.com/alibaba/druid/wiki/%E4%BD%BF%E7%94%A8ConfigFilterdriverClassName根据url自动识别这一项可配可不配,如果不配置druid会根据url自动识别dbType,然后选择相应的driverClassName(建议配置下)initialSize0初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时maxActive8最大连接池数量maxIdle8已经不再使用,配置了也没效果minIdle 最小连接池数量maxWait 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。poolPreparedStatementsfalse是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。maxOpenPreparedStatements-1要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100validationQuery 用来检测连接是否有效的sql,要求是一个查询语句。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会其作用。testOnBorrowtrue申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。testOnReturnfalse归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能testWhileIdlefalse建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。timeBetweenEvictionRunsMillis 有两个含义: 
1) Destroy线程会检测连接的间隔时间2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明numTestsPerEvictionRun 不再使用,一个DruidDataSource只支持一个EvictionRunminEvictableIdleTimeMillis 

配置一个连接在池中最小生存的时间,单位是毫秒

connectionInitSqls 物理连接初始化的时候执行的sqlexceptionSorter根据dbType自动识别当数据库抛出一些不可恢复的异常时,抛弃连接filters 属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有: 
监控统计用的filter:stat日志用的filter:log4j防御sql注入的filter:wallproxyFilters 

类型是List<com.alibaba.druid.filter.Filter>,如果同时配置了filters和proxyFilters,是组合关系,并非替换关系



为什么说Druid是“最好的数据库连接池”?体现在哪些方面?这是如何实现的?

阿里巴巴是一个重度使用关系数据库的公司,我们在生产环境中大量的使用Druid,通过长期在极高负载的生产环境中实际使用、修改和完善,让Druid逐步发展成最好的数据库连接池。Druid在监控、可扩展性、稳定性和性能方面都有明显的优势。 

首先,强大的监控特性,通过Druid提供的监控功能,可以清楚知道连接池和SQL的工作情况。 

监控SQL的执行时间、ResultSet持有时间、返回行数、更新行数、错误次数、错误堆栈信息。
SQL执行的耗时区间分布。什么是耗时区间分布呢?比如说,某个SQL执行了1000次,其中0~1毫秒区间50次,1~10毫秒800次,10~100毫秒100次,100~1000毫秒30次,1~10秒15次,10秒以上5次。通过耗时区间分布,能够非常清楚知道SQL的执行耗时情况。
监控连接池的物理连接创建和销毁次数、逻辑连接的申请和关闭次数、非空等待次数、PSCache命中率等。


其次,方便扩展。Druid提供了Filter-Chain模式的扩展API,可以自己编写Filter拦截JDBC中的任何方法,可以在上面做任何事情,比如说性能监控、SQL审计、用户名密码加密、日志等等。 

Druid内置提供了用于监控的StatFilter、日志输出的Log系列Filter、防御SQL注入攻击的WallFilter。 

阿里巴巴内部实现了用于数据库密码加密的CirceFilter,以及和Web、Spring关联监控的DragoonStatFilter。


第三,Druid集合了开源和商业数据库连接池的优秀特性,并结合阿里巴巴大规模苛刻生产环境的使用经验进行优化。 

ExceptionSorter。当一个连接产生不可恢复的异常时,例如Oracle error_code_28 session has been killed,必须立刻从连接池中逐出,否则会产生大量错误。目前只有Druid和JBoss DataSource实现了ExceptionSorter。
PSCache内存占用优化对于支持游标的数据库(Oracle、SQL Server、DB2等,不包括MySql),PSCache可以大幅度提升SQL执行性能。一个PreparedStatement对应服务器一个游标,如果PreparedStatement被缓存起来重复执行,PreparedStatement没有被关闭,服务器端的游标就不会被关闭,性能提高非常显著。在类似“SELECT * FROM T WHERE ID = ?”这样的场景,性能可能是一个数量级的提升。但在Oracle JDBC Driver中,其他的数据库连接池(DBCP、JBossDataSource)会占用内存过多,极端情况可能大于1G。Druid调用OracleDriver提供管理PSCache内部API。
LRU是一个性能关键指标,特别Oracle,每个Connection对应数据库端的一个进程,如果数据库连接池遵从LRU,有助于数据库服务器优化,这是重要的指标。Druid、DBCP、Proxool、JBoss是遵守LRU的。BoneCP、C3P0则不是。BoneCP在mock环境下性能可能还好,但在真实环境中则就不好了。

性能不是Druid的设计目标,但是测试数据表明,Druid性能比DBCP、C3P0、Proxool、JBoss都好


配置和其他的数据库连接池一样,只要对一些参数进行设置。

        <!-- 数据库连接池 -->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <!-- 数据库基本信息配置 -->
            <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/shiro"/>
            <property name="username" value="root"/>
            <property name="password" value="gaojian123"/>
            <!-- 最大并发连接数 -->
            <property name="maxActive" value="20" />
            <!-- 初始化连接数量 -->
            <property name="initialSize" value="1" />
            <!-- 配置获取连接等待超时的时间 -->
            <property name="maxWait" value="60000" />
            <!-- 最大空闲连接数 -->
            <!-- <property name="maxIdle" value="${druid.maxIdle}" /> -->
            <!-- 超过时间限制是否回收 -->
            <!-- <property name="removeAbandoned" value="${druid.removeAbandoned}" /> -->
            <!-- 超过时间限制多长; -->
            <!-- <property name="removeAbandonedTimeout" value="${druid.removeAbandonedTimeout}" /> -->
            <!-- 最小空闲连接数 -->
            <property name="minIdle" value="1" />
            <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
            <property name="timeBetweenEvictionRunsMillis" value="60000" />
            <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
            <property name="minEvictableIdleTimeMillis" value="300000" />
            <!-- 用来检测连接是否有效的sql,要求是一个查询语句-->
            <property name="validationQuery" value="SELECT 'x'" />
            <!-- 申请连接的时候检测 -->
            <property name="testWhileIdle" value="true" />
            <!-- 申请连接时执行validationQuery检测连接是否有效,配置为true会降低性能 -->
            <property name="testOnBorrow" value="false" />
            <!-- 归还连接时执行validationQuery检测连接是否有效,配置为true会降低性能  -->
            <property name="testOnReturn" value="false" />
            <!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
            <property name="poolPreparedStatements" value="true" />
            <property name="maxPoolPreparedStatementPerConnectionSize" value="50" />
            <!-- 属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有:
                    1.监控统计用的filter:stat
                    2.日志用的filter:log4j
                    3.防御SQL注入的filter:wall -->
            <!--<property name="filters" value="stat" /> -->
            <property name="proxyFilters">
                <list>
                    <ref bean="logFilter" />
                </list>
            </property>
        </bean>

        <bean id="statFilter" class="com.alibaba.druid.filter.stat.StatFilter">
            <property name="slowSqlMillis" value="3000" />
            <property name="logSlowSql" value="true" />
            <property name="mergeSql" value="true" />
        </bean>
        <!-- 配置Logback处理执行SQL -->
        <bean id="logFilter" class="com.alibaba.druid.filter.logging.Slf4jLogFilter">
            <!-- <property name="resultSetLogEnabled" value="false" /> -->
            <!-- <property name="statementExecutableSqlLogEnable" value="true" /> -->
        </bean>
          
        <bean id="wallFilter" class="com.alibaba.druid.wall.WallFilter">
            <property name="dbType" value="oracle" />
            <property name="config" ref="wall-filter-config" />
        </bean>
          
        <bean id="wall-filter-config" class="com.alibaba.druid.wall.WallConfig" init-method="init">
            <property name="dir" value="META-INF/druid/wall/oracle" />
        </bean>

在上面的配置中,通常你需要配置url、username、password、maxActive这几项。 

在DruidDataSource中,你可以不配置DriverClass,它根据url自动识别。Druid能够自动识别20多中url,常见的JDBC Driver都包括了。


※可以通过自定义FilterEventAdapter类,重写其中的方法(如:statementExecuteQueryBefore,statementExecuteQueryAfter),来扩展使用Filter。

0 0
原创粉丝点击