Druid連接池介紹及使用
- Druid的簡介
Druid是Java語言中最好的數據庫連接池,在功能、性能、擴展性方面,都超過其他數據庫連接池,包括DBCP、C3P0、Proxool、JBoss DataSource。Druid已經在阿里巴巴部署了超過600個應用,經過生產環境大規模部署的嚴苛考驗。
Druid連接池爲監控而生,內置強大的監控功能,監控特性不影響整體性能。功能強大,能防SQL注入,內置Loging能診斷Hack應用行爲
- 哪裏下載druid
maven中央倉庫: http://central.maven.org/maven2/com/alibaba/druid/
- Github上Druid常見問題
https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98
- Druid是一個JDBC組件,包括三個部分
基於Filter-Chain模式的插件體系。
DruidDataSource 高效可管理的數據庫連接池。
SQLParser
- 支持哪些數據庫
數據庫 |
支持狀態 |
mysql |
支持,大規模使用 |
oracle |
支持,大規模使用 |
sqlserver |
支持 |
postgres |
支持 |
db2 |
支持 |
h2 |
支持 |
derby |
支持 |
sqlite |
支持 |
sybase |
支持 |
- 競品對比
功能類別 |
功能 |
Druid |
DBCP |
Tomcat-jdbc |
C3P0 |
性能 |
PSCache |
是 |
是 |
是 |
是 |
LRU |
是 |
是 |
是 |
是 |
|
SLB負載均衡支持 |
是 |
否 |
否 |
否 |
|
穩定性 |
ExceptionSorter |
是 |
否 |
否 |
否 |
擴展 |
擴展 |
Filter |
|
JdbcIntercepter |
|
監控 |
監控方式 |
jmx/log/http |
jmx |
jmx |
jmx |
支持SQL級監控 |
是 |
否 |
否 |
否 |
|
Spring/Web關聯監控 |
是 |
否 |
否 |
否 |
|
|
診斷支持 |
LogFilter |
否 |
否 |
否 |
連接泄露診斷 |
logAbandoned |
否 |
否 |
否 |
|
安全 |
SQL防注入 |
是 |
無 |
無 |
無 |
支持配置加密 |
是 |
否 |
否 |
否 |
LRU 是一個性能關鍵指標,特別Oracle,每個Connection對應數據庫端的一個進程,如果數據庫連接池遵從LRU,有助於數據庫服務器優化,這是重要的指標。在測試中,Druid、DBCP、Proxool是遵守LRU的。BoneCP、C3P0則不是。
PSCache是數據庫連接池的關鍵指標。在Oracle中,類似SELECT NAME FROM USER WHERE ID = ?這樣的SQL,啓用PSCache和不啓用PSCache的性能可能是相差一個數量級的。Proxool是不支持PSCache的數據庫連接池,如果你使用Oracle、SQL Server、DB2、Sybase這樣支持遊標的數據庫,那你就完全不用考慮Proxool。
Oracle 10系列的Driver,如果開啓PSCache,會佔用大量的內存,必須做特別的處理,啓用內部的EnterImplicitCache等方法優化才能夠減少內存的佔用。這個功能只有DruidDataSource有。如果你使用的是Oracle Jdbc,你應該毫不猶豫採用DruidDataSource。
ExceptionSorter是一個很重要的容錯特性,如果一個連接產生了一個不可恢復的錯誤,必須立刻從連接池中去掉,否則會連續產生大量錯誤。這個特性,目前只有JBossDataSource和Druid實現。Druid的實現參考自JBossDataSource,經過長期生產反饋補充
- Druid使用
- Maven引入
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
- Druid結合spring配置
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="clone">
<!-- 基本屬性driverClassName、 url、user、password -->
<property name="driverClassName" value="${web.jdbc.driver}" />
<property name="url" value="${web.jdbc.url}" />
<property name="username" value="${web.jdbc.username}" />
<property name="password" value="${web.jdbc.password}" />
<!-- 配置初始化大小、最小、最大 -->
<!-- 通常來說,只需要修改initialSize、minIdle、maxActive -->
<!-- 初始化時建立物理連接的個數,缺省值爲0 -->
<property name="initialSize" value="${web.jdbc.initialSize}" />
<!-- 最小連接池數量 -->
<property name="minIdle" value="${web.jdbc.minIdle}" />
<!-- 最大連接池數量,缺省值爲8 -->
<property name="maxActive" value="${web.jdbc.maxActive}" />
<!-- 獲取連接時最大等待時間,單位毫秒。配置了maxWait之後,缺省啓用公平鎖,併發效率會有所下降,如果需要可以通過配置useUnfairLock屬性爲true使用非公平鎖 -->
<property name="maxWait" value="${jdbc.maxWait}" />
<!--
有些數據庫連接的時候有超時限制(MySQL連接在8小時後斷開),或者由於網絡中斷等原因,連接池的連接會出現失效的情況,這時候可以設置一個testWhileIdle參數爲true,
如果檢測到當前連接不活躍的時間超過了timeBetweenEvictionRunsMillis,則去手動檢測一下當前連接的有效性,在保證確實有效後才加以使用。
在檢測活躍性時,如果當前的活躍時間大於minEvictableIdleTimeMillis,則認爲需要關閉當前連接。當
然,爲了保證絕對的可用性,你也可以使用testOnBorrow爲true(即在每次獲取Connection對象時都檢測其可用性),不過這樣會影響性能。
-->
<!-- 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連接,單位是毫秒(3600000:爲1小時) -->
<property name="timeBetweenEvictionRunsMillis" value="90000" />
<!-- 配置一個連接在池中最小生存的時間,單位是毫秒(300000:爲5分鐘) -->
<property name="minEvictableIdleTimeMillis" value="1800000" />
<!-- 用來檢測連接是否有效的sql,要求是一個查詢語句。如果validationQuery爲null,testOnBorrow、testOnReturn、testWhileIdle都不會其作用。 -->
<property name="validationQuery" value="${jdbc.validationQuery}" />
<!-- 申請連接的時候檢測,如果空閒時間大於timeBetweenEvictionRunsMillis,執行validationQuery檢測連接是否有效。建議配置爲true,不影響性能,並且保證安全性-->
<property name="testWhileIdle" value="true" />
<!-- 申請連接時執行validationQuery檢測連接是否有效,做了這個配置會降低性能。缺省值:true -->
<property name="testOnBorrow" value="false" />
<!-- 歸還連接時執行validationQuery檢測連接是否有效,做了這個配置會降低性能。缺省值:false -->
<property name="testOnReturn" value="false" />
<!-- 打開PSCache,並且指定每個連接上PSCache的大小 -->
<!-- 是否緩存preparedStatement,也就是PSCache。PSCache對支持遊標的數據庫性能提升巨大,比如說oracle。在mysql5.5以下的版本中沒有PSCache功能,建議關閉掉。5.5及以上版本有PSCache,建議開啓。缺省值:false -->
<property name="poolPreparedStatements" value="true" />
<!-- 要啓用PSCache,必須配置大於0,當大於0時,poolPreparedStatements自動觸發修改爲true。在Druid中,不會存在Oracle下PSCache佔用內存過多的問題,可以把這個數值配置大一些,比如說100 -->
<property name="maxPoolPreparedStatementPerConnectionSize" value="50" />
<!-- 解密密碼必須要配置的項 -->
<property name="filters" value="config" />
<property name="connectionProperties" value="config.decrypt=true;config.decrypt.key=${web.jdbc.publickey}" />
</bean>
- 數據庫密碼加密
進入jar包所在目錄
java -cp druid-1.1.9.jar com.alibaba.druid.filter.config.ConfigTools XXXXX
web.jdbc.url=jdbc:mysql://XXXX:3306/XXX?useOldAliasMetadataBehavior=true&autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true
web.jdbc.username=用戶名
web.jdbc.password=password
web.jdbc.publickey=publicKey
若需要使用原始密碼
註釋connectionProperties 屬性即可
- 慢SQL記錄提醒
<property name="filters" value="stat,wall" />
<!-- 慢SQL記錄 -->
<bean id="stat-filter" class="com.alibaba.druid.filter.stat.StatFilter">
<!-- 慢sql時間設置,即執行時間大於200毫秒的都是慢sql -->
<property name="slowSqlMillis" value="200"/>
<property name="logSlowSql" value="true"/>
</bean>
<bean id="log-filter" class="com.alibaba.druid.filter.logging.Log4jFilter">
<property name="dataSourceLogEnabled" value="true" />
<property name="statementExecutableSqlLogEnable" value="true" />
</bean>
- SQL防禦防火牆
待研究
- 開啓web監控
<filter>
<filter-name>DruidWebStatFilter</filter-name>
<filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
<init-param>
<param-name>exclusions</param-name>
<param-value>*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*</param-value>
</init-param>
<init-param>
<param-name>profileEnable</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>DruidWebStatFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<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>
- 開啓spring類監控
<bean id="druid-stat-interceptor" class="com.alibaba.druid.support.spring.stat.DruidStatInterceptor" />
<bean id="druid-stat-pointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut" scope="prototype">
<property name="patterns">
<list>
<value>com.jf.uhrunit.service.*</value>
<value>com.jf.uhrunit.queryhelper.*</value>
</list>
</property>
</bean>
<aop:config proxy-target-class="true">
<aop:advisor advice-ref="druid-stat-interceptor" pointcut-ref="druid-stat-pointcut" />
</aop:config>