druid升級(jí)后sql監(jiān)控頁(yè)面為空白的解決
druid升級(jí)后sql監(jiān)控頁(yè)面為空白
說(shuō)明
springboot項(xiàng)目,集成druid,之前版本是1.1.10,后來(lái)直接升級(jí)成1.1.22
出現(xiàn)問(wèn)題
sql監(jiān)控為空:
數(shù)據(jù)源filter也為空:
解決過(guò)程
網(wǎng)上查詢(xún)得知,filter類(lèi)名應(yīng)為com.alibaba.druid.filter.stat.StatFilter。
借助ide,找到了stat過(guò)濾器加載的關(guān)鍵信息。
在com.alibaba.druid.spring.boot.autoconfigure.stat.DruidFilterConfiguration配置類(lèi)中,如下:
FILTER_STAT_PREFIX值為spring.datasource.druid.filter.stat
只有配置文件application.yml中有此配置項(xiàng)才會(huì)加載stat過(guò)濾器
部分druid配置項(xiàng)截圖(數(shù)據(jù)源配置省略):
配置上此選項(xiàng)即可看到監(jiān)控!
使用druid監(jiān)控sql執(zhí)行狀態(tài)
使用Druid的連接池替換掉原來(lái)的C3P0連接池,然后配置Druid的相關(guān)屬性,完成對(duì)Spring web工程的JDBC監(jiān)控。
其實(shí),我采用Druid替換其它連接池,最關(guān)鍵的一個(gè)理由是Druid有對(duì)SQL執(zhí)行的監(jiān)控統(tǒng)計(jì)功能。 :)
本文就是來(lái)看看看Druid的監(jiān)控功能。~~~ 一起玩起來(lái) : )
Druid介紹
Druid是一個(gè)JDBC組件庫(kù),包括數(shù)據(jù)庫(kù)連接池、SQL Parser等組件。DruidDataSource是最好的數(shù)據(jù)庫(kù)連接池。參考Druid wiki上的文章 <<各連接池的性能比較>>
Druild包獲取
Maven工程中添加druid依賴(lài)包:
<!-- https://mvnrepository.com/artifact/com.alibaba/druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.26</version> </dependency>
Druid使用
替換C3P0連接池
Web工程原先采用C3P0連接池的配置:
<!-- 配置數(shù)據(jù)源-C3PO --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.driverClassName}" /> <property name="jdbcUrl" value="${jdbc.url}" /> <property name="user" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="autoCommitOnClose" value="false" /> <property name="maxIdleTime" value="${cpool.maxIdleTime}" /> <property name="checkoutTimeout" value="${cpool.checkoutTimeout}" /> <property name="initialPoolSize" value="${cpool.minPoolSize}" /> <property name="minPoolSize" value="${cpool.minPoolSize}" /> <property name="maxPoolSize" value="${cpool.maxPoolSize}" /> <property name="acquireIncrement" value="${cpool.acquireIncrement}" /> <property name="maxIdleTimeExcessConnections" value="${cpool.maxIdleTimeExcessConnections}" /> </bean>
改成Druid連接池DruidDataSource
<!-- 配置數(shù)據(jù)源-druid --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="maxActive" value="20" /> <property name="initialSize" value="1" /> <property name="maxWait" value="60000" /> <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" /> </bean>
StatViewServlet配置
Druid內(nèi)置提供了一個(gè)StatViewServlet用于展示Druid的統(tǒng)計(jì)信息。
這個(gè)StatViewServlet的用途包括:
- 提供監(jiān)控信息展示的html頁(yè)面
- 提供監(jiān)控信息的JSON API
StatViewServlet是一個(gè)標(biāo)準(zhǔn)的javax.servlet.http.HttpServlet,需要配置在你web應(yīng)用中的WEB-INF/web.xml中。
<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>
配置完之后,可以通過(guò)如下格式的地址在瀏覽器訪問(wèn)查看。
http:/<host>:<port>/<context>/druid
舉個(gè)例子:
如果host為localhost,port為8080,context為Demo,那么,可以通過(guò)如下URL訪問(wèn)。
http://localhost:8080/Demo/druid
那么問(wèn)題來(lái)了
查看的時(shí)候,能否提供用戶(hù)名和密碼作為驗(yàn)證呢,而不是直接就能看JDBC執(zhí)行的狀態(tài)信息?
答案是肯定的。
需要在上述配置的情況下,配置Servlet的 loginUsername 和 loginPassword這兩個(gè)初始參數(shù)。
如:
<servlet> <servlet-name>DruidStatView</servlet-name> <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class> <init-param> <!-- 用戶(hù)名 --> <param-name>loginUsername</param-name> <param-value>druid</param-value> </init-param> <init-param> <!-- 密碼 --> <param-name>loginPassword</param-name> <param-value>druid</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>DruidStatView</servlet-name> <url-pattern>/druid/*</url-pattern> </servlet-mapping>
配置好之后,登錄之后才能訪問(wèn)。
StatFilter配置
Druid內(nèi)置提供一個(gè)StatFilter,用于統(tǒng)計(jì)監(jiān)控信息。
如果沒(méi)有配置StatFilter,那么,我們無(wú)法獲取相關(guān)統(tǒng)計(jì)信息。
比如:
無(wú)法看到SQL監(jiān)控TAB上的數(shù)據(jù)。
URI監(jiān)控TAB中,無(wú)法獲取JDBC相關(guān)的SQL執(zhí)行信息。
如何展示出這些數(shù)據(jù)呢? 解決的辦法就是配置StatFilter。
StatFilter的別名是stat,在spring中使用別名配置方式如下:
<property name="filters" value="stat" />
將上述stat添加到dataSource中去即可。
<!-- 配置數(shù)據(jù)源-druid --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <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="60000" /> <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" /> </bean>
添加完畢之后,再來(lái)看一下上述兩個(gè)TAB ( SQL監(jiān)控以及 URI監(jiān)控)下JDBC的內(nèi)容:
在SQL監(jiān)控頁(yè)面,可以很清楚地看到目前執(zhí)行SQL的具體情況,包括某條SQL語(yǔ)句執(zhí)行的時(shí)間(平均、最慢)、SQL執(zhí)行次數(shù)、SQL執(zhí)行出錯(cuò)的次數(shù)等。這些信息,可以作為系統(tǒng)SQL語(yǔ)句優(yōu)化的一個(gè)指標(biāo)。
在URI監(jiān)控頁(yè),可以清楚地看到執(zhí)行某個(gè)動(dòng)作,關(guān)聯(lián)SQL有多少,請(qǐng)求次數(shù)、執(zhí)行時(shí)間、并發(fā)數(shù)等信息。
StatFilter可以和其他的Filter配置使用,比如, 與log4j組合使用。
<property name="filters" value="stat,log4j" />
這樣,我們?cè)邳c(diǎn)擊 “記錄日志并重置” 的按鈕時(shí),Console中就會(huì)輸入JDBC相關(guān)日志,日志采用JSON的方式記錄,如:
[INFO ][2016-11-15 20:11:11,677] com.alibaba.druid.pool.DruidDataSourceStatLoggerImpl.log(DruidDataSourceStatLoggerImpl.java:77) - {"url":"jdbc:mysql://127.0.0.1:3306/Demo?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull","dbType":"mysql","name":"DataSource-958465974","activeCount":0,"poolingCount":1,"connectCount":0,"closeCount":0}
內(nèi)置Filter別名和對(duì)應(yīng)的Filter類(lèi)名如下:
別名 | Filter類(lèi)名 |
default | com.alibaba.druid.filter.stat.StatFilter |
stat | com.alibaba.druid.filter.stat.StatFilter |
mergeStat | com.alibaba.druid.filter.stat.MergeStatFilter |
encoding | com.alibaba.druid.filter.encoding.EncodingConvertFilter |
log4j | com.alibaba.druid.filter.logging.Log4jFilter |
log4j2 | com.alibaba.druid.filter.logging.Log4j2Filter |
slf4j | com.alibaba.druid.filter.logging.Slf4jLogFilter |
commonlogging | com.alibaba.druid.filter.logging.CommonsLogFilter |
慢SQL記錄
StatFilter屬性slowSqlMillis用來(lái)配置SQL慢的標(biāo)準(zhǔn),執(zhí)行時(shí)間超過(guò)slowSqlMillis的就是慢。slowSqlMillis的缺省值為3000,也就是3秒。
<bean id="stat-filter" class="com.alibaba.druid.filter.stat.StatFilter"> <property name="slowSqlMillis" value="10000" /> <property name="logSlowSql" value="true" /> </bean>
在上面的配置中,slowSqlMillis被修改為10秒,并且通過(guò)日志輸出執(zhí)行慢的SQL。
slowSqlMillis屬性也可以通過(guò)connectProperties來(lái)配置,例如:
<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>
Wallfilter配置
配置WallFilter,可以起到攔截作用,從而形成SQL的白名單和黑名單。
缺省情況下,配置裝載的目錄如下:
數(shù)據(jù)庫(kù)類(lèi)型 | 目錄 |
---|---|
mysql | META-INF/druid/wall/mysql |
oracle | META-INF/druid/wall/oracle |
sqlserver | META-INF/druid/wall/sqlserver |
postgres | META-INF/druid/wall/postgres |
從配置目錄中以下文件中讀取配置:
deny-variant.txt deny-schema.txt deny-function.txt permit-variant.txt permit-variant.txt
指定配置裝載的目錄是可以指定,例如:
<bean id="wall-filter-config" class="com.alibaba.druid.wall.WallConfig" init-method="init"> <!-- 指定配置裝載的目錄 --> <property name="dir" value="META-INF/druid/wall/mysql" /> </bean> <bean id="wall-filter" class="com.alibaba.druid.wall.WallFilter"> <property name="dbType" value="mysql" /> <property name="config" ref="wall-filter-config" /> </bean> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> ... <property name="proxyFilters"> <list> <ref bean="wall-filter"/> </list> </property> </bean>
本文實(shí)例中,采用如下的配置:
<bean id="wall-filter-config" class="com.alibaba.druid.wall.WallConfig" init-method="init"> <!-- 指定配置裝載的目錄 --> <property name="dir" value="META-INF/druid/wall/mysql" /> </bean> <bean id="wall-filter" class="com.alibaba.druid.wall.WallFilter"> <property name="dbType" value="mysql" /> <property name="config" ref="wall-filter-config" /> </bean> <!-- 配置數(shù)據(jù)源-druid --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <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="60000" /> <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="proxyFilters"> <list> <ref bean="wall-filter" /> </list> </property> </bean>
配置好Wallfilter, 我們就可以看到SQL防火墻 TAB下的內(nèi)容了。
因?yàn)槭悄J(rèn)狀態(tài),沒(méi)有配置任何攔截的屬性信息,所以,SQL的執(zhí)行都在白名單中展示出來(lái)了。
配置Spring和jdbc的關(guān)聯(lián)
最后,還有一個(gè)Tab的內(nèi)容沒(méi)有展示,那就是Spring監(jiān)控。
Druid提供了Spring和Jdbc的關(guān)聯(lián)監(jiān)控。
本文在Spring的applicationContext.xml配置文件中配置如下信息,支持方法名的攔截。
<bean id="druid-stat-interceptor" class="com.alibaba.druid.support.spring.stat.DruidStatInterceptor"> </bean> <bean id="druid-stat-pointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut" scope="prototype"> <property name="patterns"> <list> <value>com.demo.mybatis.auto.*</value> <value>com.demo.mybatis.manual.*</value> </list> </property> </bean> <aop:config> <aop:advisor advice-ref="druid-stat-interceptor" pointcut-ref="druid-stat-pointcut" /> </aop:config>
完工后,我們?cè)偃タ匆幌?,Spring監(jiān)控的TAB內(nèi)容,就可以看到相關(guān)的MyBatis Mapper執(zhí)行信息。
在Spring監(jiān)控頁(yè),可以顯示相關(guān)DAO執(zhí)行的方法,方法執(zhí)行的次數(shù)、執(zhí)行的時(shí)間等信息。
小結(jié)
通過(guò)上述幾個(gè)部分的配置,監(jiān)控頁(yè)面上所有的TAB都可以查看信息了。
當(dāng)然,Druid還有很多其他的功能,在這篇文章中就一一展示,有興趣的朋友可以在Druid的Github網(wǎng)頁(yè)上查看。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java編程實(shí)現(xiàn)NBA賽事接口調(diào)用實(shí)例代碼
這篇文章主要介紹了Java編程實(shí)現(xiàn)NBA賽事接口調(diào)用實(shí)例代碼,具有一定參考價(jià)值,需要的朋友可以了解下。2017-11-11使用IDEA創(chuàng)建一個(gè)vert.x項(xiàng)目的方法
這篇文章主要介紹了使用IDEA創(chuàng)建一個(gè)vert.x項(xiàng)目的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-09-09Hibernate中Session.get()方法和load()方法的詳細(xì)比較
今天小編就為大家分享一篇關(guān)于Hibernate中Session.get()方法和load()方法的詳細(xì)比較,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-03-03Java任務(wù)定時(shí)執(zhí)行器案例的實(shí)現(xiàn)
定時(shí)器會(huì)執(zhí)行指定的任務(wù),本文主要介紹了Java任務(wù)定時(shí)執(zhí)行器案例的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06Java中遍歷數(shù)組使用foreach循環(huán)還是for循環(huán)?
這篇文章主要介紹了Java中遍歷數(shù)組使用foreach循環(huán)還是for循環(huán)?本文著重講解for語(yǔ)句的語(yǔ)法并給出使用實(shí)例,同時(shí)總結(jié)出盡量使用foreach語(yǔ)句遍歷數(shù)組,需要的朋友可以參考下2015-06-06