一文掌握数据库连接池druid

大家好,今天我们一起聊聊数据库连接池Druid。

大纲

一文掌握数据库连接池druid

常用的数据库连接池

Apache Commons DBCP

采用标准的Java EE JDBC API来实现,同时支持JNDI,非常灵活。但是该库的最新稳定版本已经比较老了,而且在高并发场景下性能可能存在问题。

c3p0

功能齐全,能够自动维护连接池,支持JDBC3规范和JDBC2的标准扩展,性能较好。但是配置过于复杂,容易造成资源浪费。

HikariCP

专为高并发场景而设计,性能优越,具有最快的初始化速度和最小的延迟,支持JDBC4 API。但是由于需要更多的JVM资源,可能会造成资源消耗问题。

Tomcat JDBC Pool

由Apache Tomcat的开发人员创建,与Tomcat服务器集成良好,支持高度定制化配置。

Druid

支持JDBC和Oracle驱动程序,全面的性能监测,对等分布式,具有强大的扩展功能和高度定制化配置。

什么是Druid

Druid是阿里巴巴开源平台上一个数据库连接池实现,它结合了C3P0、DBCP、Proxool等DB池的优点,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况,可以说是针对监控而生的DB连接池,可以说是目前最好的连接池之一。

Druid有什么特点

高效性能

Druid采用了预处理和状态机技术,以及多线程异步IO等技术,使其在高并发、大数据量和大批量请求情况下仍能够保持稳定的高效性能。此外,Druid还具有自适应的连接池缩放功能,可以动态调整连接池大小以满足业务需求,从而避免资源的浪费与瓶颈。

监控和管理

Druid提供了完善的监控和管理功能,通过内置的Web界面可以方便地查看连接池和SQL执行情况,包括连接池的状态、使用情况、线程堆栈、SQL执行时间和执行次数等信息。这些信息可以帮助开发人员及时发现性能问题并进行调优。

安全性

Druid支持IP白名单和黑名单,可以有效地增强数据库的安全防护;同时也支持AES加密算法、密码MD5加密等数据加密技术,以保护数据库的数据安全。

可扩展性

Druid提供了丰富的插件机制,可以按需选择需要的插件进行扩展,包括监控、管理、日志、防火墙、加密等插件,同时也支持自定义扩展,开发者可以根据自身业务情况进行二次开发。

Druid是一个功能强大、性能优异、易于使用、可扩展和可靠的数据库连接池。在实际应用中,它已经被广泛应用于各种高并发、大数据量和大批量请求的业务场景中,并得到了业界的广泛认可和好评。

怎么引入Druid

Druid 0.1.18 之后版本都发布到maven中央仓库中,所以只需在项目的pom.xml中加上dependency就可以。例如:

<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>druid</artifactId>
  <version>${druid-version}</version>
 </dependency>

怎么配置Druid

参考配置

DruidDataSource大部分属性参考DBCP的,如果原来使用的DBCP,迁移会很方便。以下为参考配置:

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"
     <property name="url" value="${jdbc_url}" />
     <property name="username" value="${jdbc_user}" />
     <property name="password" value="${jdbc_password}" />

     <property name="filters" value="stat" />

     <property name="maxActive" value="20" />
     <property name="initialSize" value="1" />
     <property name="maxWait" value="6000" />
     <property name="minIdle" value="1" />

     <property name="timeBetweenEvictionRunsMillis" value="60000" />
     <property name="minEvictableIdleTimeMillis" value="300000" />

     <property name="testWhileIdle" value="true" />
     <property name="testOnBorrow" value="false" />
     <property name="testOnReturn" value="false" />

     <property name="poolPreparedStatements" value="true" />
     <property name="maxOpenPreparedStatements" value="20" />

     <property name="asyncInit" value="true" />
 </bean>

配置参数项说明

name

配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过名字来区分开来。如果没有配置,将会生成一个名字,格式是:”DataSource-” + System.identityHashCode(this). 另外配置此属性至少在1.0.5版本中是不起作用的,强行设置name会出错。

url

连接数据库的url,不同数据库不一样,必须配置参数。例如:

MySQL : jdbc:mysql://127.0.0.1:12306/mysqldb
oracle : jdbc:oracle:thin:@127.0.0.1:1521:oracledb

username

连接数据库的用户名,必须配置参数。

password

连接数据库的密码,必须配置参数。如果不希望密码直接写在配置文件中,此处可以配置为加密后的密码密文,在连接数据库时,会先解密为明文再使用。

driverClassName

根据url自动识别,此项可配可不配,如果不配置druid会根据url自动识别dbType,然后选择相应的driverClassName。

initialSize

默认0,始化时建立物理连接的个数,重要配置参数。初始化发生在显示调用init方法,或者第一次getConnection时。

maxActive

默认8,最大连接池数量,重要配置参数。

maxIdle

默认8,最大空闲连接池数量。已经不再使用,配置了也没效果。

minIdle

最小连接池数量,重要配置参数。

maxWait

获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。

poolPreparedStatements

默认值:false。是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。

maxPoolPreparedStatementPerConnectionSize

默认值:-1。要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100

validationQuery

用来检测连接是否有效的sql,要求是一个查询语句,常用select ‘x’,重要配置参数。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。

validationQueryTimeout

单位:秒,检测连接是否有效的超时时间,重要配置参数。底层调用jdbc Statement对象的void setQueryTimeout(int seconds)方法

testOnBorrow

默认值:true。申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。

testOnReturn

默认值:false。归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。

testWhileIdle

默认值:false。建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。

keepAlive

默认值:false,1.0.28版本后的参数项。连接池中的minIdle数量以内的连接,空闲时间超过minEvictableIdleTimeMillis,则会执行keepAlive操作。

timeBetweenEvictionRunsMillis

默认值:1分钟,1.0.14版本后的参数项。有两个含义:1)Destroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接;2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明。

numTestsPerEvictionRun

默认值:30分钟,1.0.14版本后的参数项。不再使用,一个DruidDataSource只支持一个EvictionRun。

minEvictableIdleTimeMillis

连接保持空闲而不被驱逐的最小时间。

connectionInitSqls

物理连接初始化的时候执行的sql。

exceptionSorter

默认值:根据dbType自动识别。当数据库抛出一些不可恢复的异常时,抛弃连接。

filters

属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有:监控统计用的filter:stat;日志用的filter:log4j;防御sql注入的filter:wall。

proxyFilters

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

配置Druid日志

log4j配置

<!--druid的日志记录追加器-->
        <RollingFile name="druidSqlRollingFile" fileName="./logs/druid-sql.log"
                     filePattern="logs/$${date:yyyy-MM}/api-%d{yyyy-MM-dd}-%i.log.gz">
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss}] %-5level %L %M - %msg%xEx%n"/>
            <Policies>
                <SizeBasedTriggeringPolicy size="500 MB"/>
                <TimeBasedTriggeringPolicy/>
            </Policies>
        </RollingFile>
<!--记录druid-sql的记录-->
        <logger name="druid.sql.Statement" level="debug" additivity="false">
            <appender-ref ref="druidSqlRollingFile"/>
        </logger>
        <logger name="druid.sql.Statement" level="debug" additivity="false">
            <appender-ref ref="druidSqlRollingFile"/>
        </logger>

配置慢sql监控

Druid内置提供一个StatFilter,用于统计监控信息。StatFilter的别名是stat,这个别名映射配置信息保存在druid-xxx.jar!/META-INF/druid-filter.properties。

方式一

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
   ... ...
   <property name="filters" value="stat,log4j" />
  </bean>

在上面的配置中,StatFilter和Log4jFilter组合使用。

<bean id="stat-filter" class="com.alibaba.druid.filter.stat.StatFilter">
 <property name="slowSqlMillis" value="10000" />
 <property name="logSlowSql" value="true" />
</bean>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
 init-method="init" destroy-method="close">
 ... ...
 <property name="filters" value="log4j" />
 <property name="proxyFilters">
  <list>
   <ref bean="stat-filter" />
  </list>
 </property>
</bean>

别名配置是通过filters属性配置的,filters属性的类型是String。如果需要通过bean的方式配置,使用proxyFilters属性。

其中filters和proxyFilters属性是组合关系的,不是替换的,在上面的配置中,dataSource有了两个Filter,StatFilter和Log4jFilter。以上配置为监控超过10秒的慢sql,根据实际场景调整。

方式二

slowSqlMillis属性也可以通过connectProperties来配置:

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
   ... ...
   <property name="filters" value="stat" />
   <property name="connectionProperties" value="druid.stat.slowSqlMillis=5000" />
  </bean>

配置数据库密码加密

在配置文件中配置数据库密码时,采用明文的方式,密码容易暴露,druid可以采用密码加密的方式。

生成密码密文

数据库密码为123456,采用以下命令生成密码密文及加解密公私钥对。

java -cp druid-1.0.27.jar com.alibaba.druid.filter.config.ConfigTools 123456
privateKey:MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEApx1gO8tPiwF+NrMAm0AWYpu+38oiVJ3Y0xaSDpDkcwq/mRLoopRpkXKNnJUjw9GsSCA5FsbyzgbU00gchJBlWQIDAQABAkBCC7UVzKNSL7PfEF2j/e8a56zHK07oHD4uJtRwl0kCQdCJyzn0pKt3AwHgBHtnx4DoKzdj86txx047fCTvpoLRAiEA2SvD6r7cInI8kqbgePzgeFeeVhhjNuXDAAzekBSoKHUCIQDE/nbV9dcsaMBfzcgVpd83rcVUANcVczGnnjshUZRM1QIgPUOTaU2eXDlNzTE2ceskh85v5GnM01fNwt3ei1bIeWECIQCn+b/FREL9mDjpuGPzqaQEK0XHEoxUuwxNPIx5JcIKHQIgICtDfCbr6zA8Tk8jPIxO2p9V5GvoSACh916XQjBpK88=
publicKey:MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKcdYDvLT4sBfjazAJtAFmKbvt/KIlSd2NMWkg6Q5HMKv5kS6KKUaZFyjZyVI8PRrEggORbG8s4G1NNIHISQZVkCAwEAAQ==
password:CD5rXr8fgN2pColHLFKR1vWKC/Mps6Lh5luP6BgGVSIaXBk7yscV9z8p9ZDU8R5qEZ2Yn9BDXiM3KyX3kAwvpQ==

DruidDataSource配置

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
   ... ...
    <property name="password" value="${datasource.passwd}" />
   <property name="filters" value="config" />
   <property name="connectionProperties" value="config.decrypt=true;config.decrypt.key=${datasource.key.pub}" />
  </bean>

此处的datasource.passwd为生成密码密文时生成的password的值;datasource.key.pub为生成密码密文时生成的publicKey的值。

总结

Druid是一个功能强大、性能优异、易于使用、可扩展和可靠的数据库连接池。在实际应用中,它已经被广泛应用于各种高并发、大数据量和大批量请求的业务场景中,并得到了业界的广泛认可和好评。使用它可以帮我们创建和管理数据库连接,可以使用慢sql等监控功能,使用数据库密码加密等丰富的扩展功能。在选用Druid版本时,应充分了解对应版本出现的问题,评估是否符合应用服务的业务场景。如1.0.9-1.0.25版本,存在当表结构发生变化(新增字段)时,会报java.sql.SQLException: Protocol violation 错误;1.0.27版本,在出现主键冲突后,现有连接池中的链接报iava.sql.sqLRecoverableException:closed statement错误。

点击这里给我留言吧

原文始发于微信公众号(扬哥手记):一文掌握数据库连接池druid

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/239512.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!