JAVA && Spring && SpringBoot2.x — 學(xué)習(xí)目錄
SpringBoot默認(rèn)的數(shù)據(jù)源是:org.apache.tomcat.jdbc.pool.DataSource粘室。但畢竟Druid是Java語言中最好的數(shù)據(jù)庫連接池初橘,并且可以提供強大的監(jiān)控和擴展功能,因此這里介紹一下springboot如何整合druid袱吆。
1. 引入依賴
<!--druid數(shù)據(jù)庫連接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.9</version>
</dependency>
mybatis+mysql驅(qū)動依賴
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
2. SpringBoot整合Druid的yml配置文件
spring:
datasource:
name: mysql_test
type: com.alibaba.druid.pool.DruidDataSource
#druid相關(guān)配置
druid:
#監(jiān)控統(tǒng)計攔截的filters
filters: stat,config,wall
filter:
wall:
#檢查UPDATE域醇,DELETE語句是否有where條件将鸵,默認(rèn)false
config:
update-where-none-check: true
delete-where-none-check: true
# 開啟防火墻
enabled: true
driver-class-name: com.mysql.cj.jdbc.Driver
#基本屬性
url: jdbc:mysql://localhost:3306/mydb
username: root
password: 123456
#初始化連接數(shù)
initial-size: 10
#最小活躍連接數(shù)
min-size: 5
#最大活躍連接數(shù)
max-active: 20
#獲取連接的等待時間
max-wait: 60000
#間隔多久進(jìn)行一次檢查误堡,檢查需要關(guān)閉的空閑連接
time-between-eviction-runs-millis: 60000
#一個連接在池中最小的生存時間(5分鐘)
min-evictable-idle-time-millis: 300000
validation-query: SELECT 'X'
# 空閑時間大于 time-between-eviction-runs-millis檢測連接
test-while-idle: true
# 申請連接時是否檢測連接(開啟影響性能)
test-on-borrow: false
#歸還連接時是否檢測連接(開啟影響性能)
test-on-return: false
#打開PSCache,并指定每個連接上PSCache的大小丢习。oracle設(shè)為true牵触,mysql設(shè)為false。分庫分表較多推薦設(shè)置為false
#第三發(fā)連接池在使用的時候咐低,獲取到Connection后揽思,使用完畢,調(diào)用關(guān)閉方法见擦,并沒有將Connection關(guān)閉钉汗,只是放回到連接池中
#如果調(diào)用這個方法,而沒有手動關(guān)閉PreparedStatement鲤屡,就可能造成內(nèi)存溢出损痰,但是JDK1.7實現(xiàn)了AutoCloseable接口,就不需要關(guān)閉了
pool-prepared-statements: false
max-pool-prepared-statement-per-connection-size: -1
connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500;config.decrypt=true;config.decrypt.key=XXX
3. DruidDataSource配置屬性列表
配置 | 缺省值 | 說明 |
---|---|---|
name | 如果存在多個數(shù)據(jù)源执俩,監(jiān)控的時候可以通過名字區(qū)分開來徐钠。如果沒有配置,將自動生成一個名字役首。 | |
url | 連接數(shù)據(jù)庫的url | |
username | 連接數(shù)據(jù)庫的用戶名 | |
password | 連接數(shù)據(jù)庫的密碼,如果你不希望密碼直接寫在配置文件中显拜,可以使用ConfigFilter衡奥。詳細(xì)看這里 | |
driverClassName | 根據(jù)url自動識別 | 數(shù)據(jù)庫驅(qū)動 |
initialSize | 0 | 初始化時建立的物理連接個數(shù)。初始化發(fā)生在顯示調(diào)用init方法远荠,或者第一次getConnection時 |
maxActive | 8 | 最大的連接池數(shù)量 |
maxIdle | 8 | 已廢棄矮固,配置后也不再生效 |
minIdle | 最小連接池數(shù)量 | |
maxWait | 獲取連接的最大等待時間,單位毫秒譬淳。配置了maxWait之后档址,缺省啟用公平鎖,并發(fā)效率會有所下降邻梆,如果需要可以通過配置useUnfairLock屬性為true使用非公平鎖守伸。詳細(xì)看這里 | |
poolPreparedStatement | false | 是否緩存preparedStatement,也就是PSCache浦妄,PSCache對支持游標(biāo)的數(shù)據(jù)庫性能提升巨大尼摹。比如oracle见芹。在mysql下建議關(guān)閉。 |
maxPoolPreparedStatementPerConnectionSize | -1 | 要啟用PSCache蠢涝,必須配置大于0玄呛。當(dāng)大于0時,poolPreparedStatement將自動觸發(fā)修改為true和二。在Druid中徘铝,不會存在Oracle下PSCache占用內(nèi)存過多的問題,可以吧這個數(shù)組配置大一些惯吕。 |
validationQuery | 用來檢測連接是否有效的sql庭砍,要求是一個查詢語句,常有select 'x'混埠。如果validationQuery為null怠缸,testOnBorrow、testOnReturn钳宪、testWhileIdle都不會起作用揭北。 | |
validationQueryTimeout | 單位:秒,檢測連接是否有效的超時時間吏颖,底層調(diào)用jdbc Statement對象的void setQueryTimeout(int seconds)方法 | |
testOnBorrow | true | 申請連接時執(zhí)行validationQuery檢測連接是否有效搔体,做了這個配置會降低性能 |
testOnReturn | false | 歸還連接時執(zhí)行validationQuery檢測連接是否有效,做了這個配置會降低性能 |
testWhileIdle | false | 建議配置true半醉,不影響性能疚俱,并且保證安全。申請連接的時候檢測缩多,如果空閑時間大于timeBetweenEvictionRunsMillis呆奕,執(zhí)行validationQuery檢測連接是否有效。 |
timeBetweenEvictionRunsMillis | 1分鐘(1.0.14) | 有兩個含義:(1)Destroy線程會檢測連接的間隔時間衬吆,如果連接空閑時間大于等于minEvictableIdleTimeMillis則關(guān)閉物理連接(2)testWhileIdle判斷依據(jù)梁钾。 |
minEvictableIdleTimeMillis | 連接保存空閑而不被驅(qū)逐(關(guān)閉物理連接)的最長時間 | |
connectionInitSqls | 物理連接初始化的時候執(zhí)行的sql | |
exceptionSorter | 根據(jù)dbtype判斷 | 當(dāng)數(shù)據(jù)庫拋出一些不可恢復(fù)異常時,拋棄連接 |
filters | 屬性是字符串逊抡,通過別名的方式配置擴展插件姆泻,常用的插件(1)監(jiān)控統(tǒng)計:filter:stat(2)日志用的:filter:log4j(3)防御sql注入:filter:wall | |
proxyFilters | 類型是List,如果同時配置了filters和proxyFilters冒嫡,是組合關(guān)系而非替換關(guān)系拇勃。 | |
connection-properties | 配置連接的信息(開啟慢查詢,請求密碼等) |
4. Druid監(jiān)控配置
配置druid數(shù)據(jù)源之后孝凌,就可訪問http:localhost:8080/druid/index.html進(jìn)行查看監(jiān)控頁面了方咆。但如何設(shè)置監(jiān)控的配置信息呢?
4.1. 監(jiān)控身份驗證信息
- 在javaConfig中的配置
使用@Configuration+@Bean注解胎许,在java代碼中配置spring容器的bean
@Configuration
public class DruidMonitorConfiguration {
//stat [斯達(dá)特] 身份 Registration [瑞這死得神] 注冊 [注誒得] druid
@Bean
public ServletRegistrationBean DruidStatViewServlet() {
//ServletRegistrationBean提供類的進(jìn)行注冊.
ServletRegistrationBean servletRegistrationBean =
new ServletRegistrationBean(new StatViewServlet(), "/druid2/*");
//白名單
servletRegistrationBean.addInitParameter("allow", "127.0.0.1");
//IP黑名單 (存在共同時峻呛,deny優(yōu)先于allow) : 如果滿足deny的話提示:Sorry, you are not permitted to view this page.
servletRegistrationBean.addInitParameter("deny", "192.168.1.73");
//登錄名密碼
servletRegistrationBean.addInitParameter("loginUsername", "name");
servletRegistrationBean.addInitParameter("loginPassword", "password");
//是否能夠重置數(shù)據(jù)
servletRegistrationBean.addInitParameter("resetEnable", "false");
return servletRegistrationBean;
}
}
可訪問http://localhost:8080/druid2/login.html進(jìn)行訪問
- 在配置文件中的配置
也可以在上面的yml配置文件中配置罗售。
spring:
datasource:
name: mysql_test
type: com.alibaba.druid.pool.DruidDataSource
#druid相關(guān)配置
druid:
#配置監(jiān)控頁面訪問登錄名稱/密碼
stat-view-servlet:
login-username: admin
login-password: password
url-pattern: /yy/*
#禁止手動重置監(jiān)控數(shù)據(jù)
reset-enable: false
轉(zhuǎn)換為properties文件:
spring.datasource.druid.stat-view-servlet.url-pattern=/druid/*
spring.datasource.druid.stat-view-servlet.reset-enable=false
spring.datasource.druid.stat-view-servlet.login-username=admin
spring.datasource.druid.stat-view-servlet.login-password=123456
4.2 Spring監(jiān)控,對內(nèi)部各接口調(diào)用的監(jiān)控
spring.datasource.druid.aop-patterns=com.company.project.service.*,
com.company.project.dao.*,com.company.project.controller.*,com.tellme.mapper.*
4.2 Druid的慢sql
在sql監(jiān)控中钩述,有一項關(guān)于sql執(zhí)行最慢時間的統(tǒng)計寨躁,但是只要一個值,就是一條sql語句最慢的執(zhí)行時間記錄牙勘,其他執(zhí)行時間是看不到的职恳,只能通過總時間來進(jìn)行粗略的估計,還存在一個問題:一旦項目重啟方面,這些記錄就全都沒有放钦,因此制定對應(yīng)的日志輸出策略是及其有必要的。
可以在springboot中可以通過配置文件connection-properties配置慢查詢恭金。此時設(shè)置的慢sql的時間是1毫秒操禀,所以執(zhí)行時間大于1毫秒的都會被紅色標(biāo)注。
# 配置StatFilter (開啟慢sql)
spring.datasource.druid.filter.stat.enabled=true
spring.datasource.druid.filter.stat.db-type=h2
spring.datasource.druid.filter.stat.log-slow-sql=true
spring.datasource.druid.filter.stat.slow-sql-millis=1
附錄:
1. 公平鎖的效率為什么比非公平鎖低
CPU在調(diào)度線程的時候横腿,會在等待線程例隨機挑選一個線程颓屑,由于隨機性,故不能保證線程先到先得耿焊。這樣就會產(chǎn)生饑餓現(xiàn)象:即有些線程優(yōu)先級低的線程可能永遠(yuǎn)無法獲取CPU的執(zhí)行權(quán)揪惦,優(yōu)先級高的線程會不斷搶占資源。于是就有了公平鎖罗侯。
公平鎖可以保證線程按照時間順序執(zhí)行器腋,避免饑餓現(xiàn)象的產(chǎn)生,但是公平鎖效率很低钩杰,因為要保證順序執(zhí)行纫塌,就得維護一個有序隊列。
截取自——Java并發(fā)之公平鎖
2. mysql下為什么建議關(guān)閉poolPreparedStatement
第三方的數(shù)據(jù)庫連接池榜苫,使用的時候护戳,獲取到Connection之后,使用完成垂睬,調(diào)用的關(guān)閉方法(close()) ,并沒有將Connection關(guān)閉抗悍,只是放回到連接池中驹饺,如果調(diào)用的這個方法,而沒有手動關(guān)閉PreparedStatement等缴渊,則這個PreparedStatement并沒有關(guān)閉赏壹,這樣會使得開發(fā)的程序內(nèi)存急速增長,java的內(nèi)存回收機制可能跟不上速度衔沼,最終造成Out of memory Error蝌借。
如果使用JDK 7就不用了昔瞧,他們都實現(xiàn)了java.lang.AutoCloseable
截取自——百度知道
文章參考
數(shù)據(jù)連接池默認(rèn)配置帶來的坑testOnBorrow=false,cloes_wait 終于解決了
(官網(wǎng))https://github.com/alibaba/druid/wiki/配置_StatViewServlet配置
阿里druid-spring-boot-starter 配置(配置完成后不需要在配置類寫)根據(jù)阿里官方個人整理
2509-Druid監(jiān)控功能的深入使用與配置-基于SpringBoot-完全使用 .properties配置文件