Druid是一個很是優秀的數據庫鏈接池。在功能、性能、擴展性方面,都超過其餘數據庫鏈接池,包括DBCP、C3P0、BoneCP、Proxool、JBoss DataSource。css
Druid已經在阿里巴巴部署了超過600個應用,通過一年多生產環境大規模部署的嚴苛考驗。java
Druid是一個JDBC組件,它包括三個部分:mysql
基於Filter-Chain模式的插件體系。git
DruidDataSource 高效可管理的數據庫鏈接池。github
SQLParserweb
Druid提供了一個高效、功能強大、可擴展性好的數據庫鏈接池。從DBCP遷移到Druid,只須要修改數據源的實現類就能夠了。spring
Druid內置了一個功能強大的StatFilter插件能夠監控數據庫訪問性能,能夠清楚知道鏈接池和SQL的工做狀況。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命中率等。
直接把數據庫密碼寫在配置文件中,這是很差的行爲,容易致使安全問題。DruidDruiver和DruidDataSource都支持PasswordCallback。
Druid提供了不一樣的LogFilter,可以支持Common-Logging、Log4j和JdkLog,你能夠按須要選擇相應的LogFilter,監控你應用的數據庫訪問狀況。
若是你要對JDBC層有編程的需求,能夠經過Druid提供的Filter機制,很方便編寫JDBC層的擴展插件。
Druid在DruidDataSourc和ProxyDriver上提供了Filter-Chain模式的擴展API,相似Serlvet的Filter,配置Filter攔截JDBC的方法調用。
SQL Parser是Druid的一個重要組成部分,它提供了MySql、Oracle、Postgresql、SQL-92的SQL的完整支持,這是一個手寫的高性能SQL Parser,支持Visitor模式,使得分析SQL的抽象語法樹很方便。
簡單SQL語句用時10微秒之內,複雜SQL用時30微秒。
經過Druid提供的SQL Parser能夠在JDBC層攔截SQL作相應處理,好比防護SQL注入(WallFilter)、合併統計沒有參數化的SQL(StatFilter的mergeSql)、SQL格式化、分庫分表。
http://blog.csdn.net/qq_30444003/article/details/50795116
<style>table th:first-of-type { width: 100px;}</style>
配置 | 缺省值 | 說明 |
---|---|---|
name | 配置這個屬性的意義在於,若是存在多個數據源,監控的時候能夠經過名字來區分開來。若是沒有配置,將會生成一個名字,格式是:"DataSource-" + System.identityHashCode(this). 另外配置此屬性至少在1.0.5版本中是不起做用的,強行設置name會出錯。詳情-點此處。 | |
url | 鏈接數據庫的url,不一樣數據庫不同。例如:<br />mysql : jdbc:mysql://10.20.153.104:3306/druid2<br /> oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnauto | |
username | 鏈接數據庫的用戶名 | |
password | 鏈接數據庫的密碼。若是你不但願密碼直接寫在配置文件中,可使用ConfigFilter。詳細看這裏 | |
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檢測鏈接是否有效。 |
timeBetweenEvictionRunsMillis | 1分鐘(1.0.14) | 有兩個含義:<br />1) Destroy線程會檢測鏈接的間隔時間,若是鏈接空閒時間大於等於minEvictableIdleTimeMillis則關閉物理鏈接。<br />2) testWhileIdle的判斷依據,詳細看testWhileIdle屬性的說明 |
numTestsPerEvictionRun | 30分鐘(1.0.14) | 再也不使用,一個DruidDataSource只支持一個EvictionRun |
minEvictableIdleTimeMillis | 鏈接保持空閒而不被驅逐的最長時間 | |
connectionInitSqls | 物理鏈接初始化的時候執行的sql | |
exceptionSorter | 根據dbType自動識別 | 當數據庫拋出一些不可恢復的異常時,拋棄鏈接 |
filters | 屬性類型是字符串,經過別名的方式配置擴展插件,經常使用的插件有:<br />監控統計用的filter:stat<br />日誌用的filter:log4j<br />防護sql注入的filter:wall | |
proxyFilters | 類型是List<com.alibaba.druid.filter.Filter>,若是同時配置了filters和proxyFilters,是組合關係,並不是替換關係 |
https://github.com/alibaba/druid/wiki
https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98
咱們使用的是Spring boot + mybatis + Druid(官方start)的架構
目前Spring Boot中默認支持的鏈接池有dbcp,dbcp2, tomcat, hikari四種鏈接池。
因爲Druid暫時不在Spring Bootz中的直接支持。如今阿里官方對Spring Boot作了優化,寫了一個start,咱們在Spring Boot項目中直接依賴便可。
<!-- 數據庫驅動 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- Mybatis --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.0</version> </dependency> <!--Mybatis 分頁插件 pagehelper --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.1.1</version> </dependency> <!-- Druid鏈接池包 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.1</version> </dependency>
#https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter spring.datasource.druid.url=jdbc:mysql://localhost:3306/ssb_test spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver spring.datasource.druid.username=root spring.datasource.druid.password=root # 初始化大小,最小,最大 spring.datasource.druid.initial-size=5 spring.datasource.druid.min-idle=5 spring.datasource.druid.max-active=20 # 配置獲取鏈接等待超時的時間 spring.datasource.druid.max-wait=60000 # 配置間隔多久才進行一次檢測,檢測須要關閉的空閒鏈接,單位是毫秒 spring.datasource.druid.time-between-eviction-runs-millis=60000 # 配置一個鏈接在池中最小生存的時間,單位是毫秒 spring.datasource.druid.min-evictable-idle-time-millis=300000 #檢測鏈接是否有效的sql spring.datasource.druid.validation-query=SELECT 'x' spring.datasource.druid.validation-query-timeout=60000 spring.datasource.druid.test-while-idle=true spring.datasource.druid.test-on-borrow=false spring.datasource.druid.test-on-return=false # PSCache Mysql下建議關閉 spring.datasource.druid.pool-prepared-statements=false spring.datasource.druid.max-pool-prepared-statement-per-connection-size=-1 #spring.datasource.druid.max-open-prepared-statements= #等價於上面的max-pool-prepared-statement-per-connection-size #mybatis #entity掃描的包名 mybatis.type-aliases-package=com.xiaolyuh.domain.model #Mapper.xml所在的位置 mybatis.mapper-locations=classpath*:/mybaits/*Mapper.xml #開啓MyBatis的二級緩存 mybatis.configuration.cache-enabled=true #pagehelper pagehelper.helperDialect=mysql pagehelper.reasonable=true pagehelper.supportMethodsArguments=true pagehelper.params=count=countSql
到這裏咱們數據源就配置好了,寫一個測試類咱們能夠查看數據源是否生效。
package com.xiaolyuh; import com.alibaba.fastjson.JSON; import com.xiaolyuh.config.DruidDataSourceProperty; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.ApplicationContext; import org.springframework.test.context.junit4.SpringRunner; import javax.sql.DataSource; @RunWith(SpringRunner.class) @SpringBootTest public class DataSourceTests { @Autowired ApplicationContext applicationContext; @Test public void testDataSource() throws Exception { // 獲取配置的數據源 DataSource dataSource = applicationContext.getBean(DataSource.class); // 查看配置數據源信息 System.out.println(dataSource.getClass().getName()); } }
打印日誌:
com.alibaba.druid.pool.DruidDataSource {"connectionProperties":"druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000","driverClassName":"com.mysql.jdbc.Driver","filters":"stat,wall,log4j","initialSize":5,"maxActive":20,"maxPoolPreparedStatementPerConnectionSize":-1,"maxWait":60000,"minEvictableIdleTimeMillis":300000,"minIdle":5,"password":"root","poolPreparedStatements":false,"testOnBorrow":false,"testOnReturn":false,"testWhileIdle":true,"timeBetweenEvictionRunsMillis":60000,"url":"jdbc:mysql://localhost:3306/ssb_test","useGlobalDataSourceStat":true,"username":"root","validationQuery":"SELECT 'x'"} 2017-07-02 11:29:04.183 INFO 340 --- [ Thread-2] o.s.w.c.s.GenericWebApplicationContext : Closing org.springframework.web.context.support.GenericWebApplicationContext@11fc564b: startup date [Sun Jul 02 11:28:58 CST 2017]; root of context hierarchy
下面咱們來講一下Druid監控的配置:
# 配置監控統計攔截的filters,去掉後監控界面sql沒法統計,'wall'用於防火牆 spring.datasource.druid.filters=stat,wall,log4j
使用這個filter的配置,開啓對監控的支持。屬性類型是字符串,經過別名的方式配置擴展插件,經常使用的插件有:
在application.properties文件中加入以下配置:
# WebStatFilter配置,說明請參考Druid Wiki,配置_配置WebStatFilter #啓動項目後訪問 http://127.0.0.1:8080/druid #是否啓用StatFilter默認值true spring.datasource.druid.web-stat-filter.enabled=true spring.datasource.druid.web-stat-filter.url-pattern=/* spring.datasource.druid.web-stat-filter.exclusions=*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/* #缺省sessionStatMaxCount是1000個 spring.datasource.druid.web-stat-filter.session-stat-max-count=1000 #關閉session統計功能 spring.datasource.druid.web-stat-filter.session-stat-enable=false #配置principalSessionName,使得druid可以知道當前的session的用戶是誰 #若是你session中保存的是非string類型的對象,須要重載toString方法 spring.datasource.druid.web-stat-filter.principalSessionName=xxx.user #若是user信息保存在cookie中,你能夠配置principalCookieName,使得druid知道當前的user是誰 spring.datasource.druid.web-stat-filter.principalCookieName=xxx.user #druid 0.2.7版本開始支持profile,配置profileEnable可以監控單個url調用的sql列表。 spring.datasource.druid.web-stat-filter.profile-enable=false
在application.properties文件中加入以下配置:
# StatViewServlet配置,說明請參考Druid Wiki,配置_StatViewServlet配置 #啓動項目後訪問 http://127.0.0.1:8080/druid #是否啓用StatViewServlet默認值true spring.datasource.druid.stat-view-servlet.enabled=true spring.datasource.druid.stat-view-servlet.urlPattern=/druid/* #禁用HTML頁面上的「Reset All」功能 spring.datasource.druid.stat-view-servlet.resetEnable=false #用戶名 spring.datasource.druid.stat-view-servlet.loginUsername=admin #密碼 spring.datasource.druid.stat-view-servlet.loginPassword=admin #IP白名單(沒有配置或者爲空,則容許全部訪問) spring.datasource.druid.stat-view-servlet.allow=127.0.0.1,192.168.163.1 #IP黑名單 (存在共同時,deny優先於allow) spring.datasource.druid.stat-view-servlet.deny=192.168.1.73
瀏覽器中輸入:http://localhost/druid
輸入用戶名和密碼,上面配置的。
https://github.com/wyh-spring-ecosystem-student/spring-boot-student/tree/releases
spring-boot-student-mybatis-druid-2 工程