實(shí)踐 Druid 作為 SpringBoot 工程的數(shù)據(jù)源添加 SQL 監(jiān)控

在大型業(yè)務(wù)系統(tǒng)上線后,為了保證系統(tǒng)能夠更好地持續(xù)穩(wěn)定運(yùn)行,及時(shí)發(fā)現(xiàn)各種故障(代碼缺陷、SQL性能問題、服務(wù)器CPU/磁盤參數(shù)指標(biāo)和各類業(yè)務(wù)異常等),因此需要針對(duì)系統(tǒng)開發(fā)各種監(jiān)控功能。在微服務(wù)架構(gòu)下的各類業(yè)務(wù)平臺(tái)中,針對(duì)SQL進(jìn)行監(jiān)控,并根據(jù)業(yè)務(wù)的發(fā)展情況及時(shí)進(jìn)行調(diào)優(yōu)尤為重要。如果讓中間件或者業(yè)務(wù)研發(fā)團(tuán)隊(duì)自己根據(jù)業(yè)務(wù)特征定制化開發(fā)一套SQL的監(jiān)控系統(tǒng),可能既費(fèi)時(shí)費(fèi)力,又不一定能夠達(dá)到預(yù)定的結(jié)果。本文將介紹業(yè)界較為流行的Druid數(shù)據(jù)源連接池插件,并跟其他幾款熱門的數(shù)據(jù)源連接池進(jìn)行對(duì)比分析,最后給出在Spring Boot工程中集成該數(shù)據(jù)源連接池的實(shí)踐方法。

1. Druid數(shù)據(jù)庫連接池介紹

Druid數(shù)據(jù)源連接池來源于阿里巴巴,是淘寶和支付寶專用數(shù)據(jù)庫連接池。事實(shí)上,它不僅僅是一個(gè)數(shù)據(jù)庫連接池,還包含一個(gè)ProxyDriver、一系列內(nèi)置的JDBC組件庫、一個(gè) SQL Parser。支持所有JDBC兼容的數(shù)據(jù)庫,包括Oracle、MySql、Derby、Postgresql、SQL Server、H2等等。Druid針對(duì)Oracle和MySql做了特別優(yōu)化,比如Oracle的PSCache內(nèi)存占用優(yōu)化,MySql的ping檢測(cè)優(yōu)化。Druid提供了諸如MySql、Oracle、Postgresql、SQL-92等SQL語句的完美支持,是一個(gè)手寫的高性能SQL Parser,支持Visitor模式,使得分析SQL的抽象語法樹很方便。它執(zhí)行簡單SQL語句耗時(shí)在10微秒以內(nèi),對(duì)于復(fù)雜的SQL語句耗時(shí)也在30微秒左右。另外,通過Druid提供的SQL Parser可以在JDBC層面上攔截SQL并進(jìn)行相應(yīng)處理,比如說分庫分表、SQL安全審計(jì)等。Druid也能防御SQL注入攻擊,WallFilter就是通過Druid的SQL Parser分析語義實(shí)現(xiàn)的。

2. 與其他幾種數(shù)據(jù)庫連接池進(jìn)行對(duì)比

通過下面的表格先來看下Druid與當(dāng)前比較流行的其他幾款數(shù)據(jù)源連接池的對(duì)比:

功能 dbcp druid c3p0 tomcat-jdbc HikariCP
支持PSCache
監(jiān)控 jmx jmx/log/http jmx,log jmx jmx
擴(kuò)展
sql攔截及解析 支持
代碼 簡單 中等 復(fù)雜 簡單 簡單
特點(diǎn) 依賴common-pool 阿里開源,功能全面 代碼邏輯復(fù)雜,且不易維護(hù) 功能簡單,起源于boneCP
連接池管理 LinkedBlockingDeque 數(shù)組 更新 FairBlockingQueue threadlocal+CopyOnWriteArrayList

從上面對(duì)比的表格中,可以看到druid功能最為全面,具備sql攔截等功能,其中統(tǒng)計(jì)數(shù)據(jù)較為全面,具有良好的擴(kuò)展性。雖然在性能方面比HikariCP略差,但是綜合其他方面來考慮在做技術(shù)選型的時(shí)候,可以選擇Druid作為數(shù)據(jù)源連接池組件來用。

3. 動(dòng)手在Spring-Boot工程中添加Druid實(shí)踐

本文前面兩節(jié)都是主要講了理論,相對(duì)比較枯燥。下面這一節(jié)將從實(shí)踐的角度,來一步一步向大家展示如何在Spring Boot工程中添加Druid連接池進(jìn)行業(yè)務(wù)級(jí)的SQL監(jiān)控。

版本環(huán)境
Spring Boot 1.4.1.RELEASE、Druid 1.0.12、JDK 1.8

在工程中添加Druid的pom依賴
因?yàn)榘⒗镩_源了Druid的數(shù)據(jù)源連接池源碼,我們可以通過maven倉庫可以獲得jar包依賴。訪問http://mvnrepository.com/artifact/com.alibaba/druid選擇自己項(xiàng)目需要的版本(在本次集成中選擇的是1.0.12),點(diǎn)擊進(jìn)入后復(fù)制maven內(nèi)容到pom.xml內(nèi)即可,如下所示:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.0.12</version>
</dependency>

在自己工程中添加完以上Druid數(shù)據(jù)源連接池的依賴后,記得在Intellij中點(diǎn)擊下"Enable Auto import"選項(xiàng)即可自動(dòng)下載maven依賴的jar到本地.m2目錄并構(gòu)建到項(xiàng)目中。添加Druid至Spring Boot工程中就這么Easy,這么快捷。

在Spring Boot工程中添加Druid配置
在上面我們已經(jīng)將Druid添加至項(xiàng)目中,接下來需要修改Spring Boot的application.yml配置文件,來添加Druid數(shù)據(jù)源連接池的支持,如下所示:

server.port=8888
# 數(shù)據(jù)庫訪問配置
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=gbk&zeroDateTimeBehavior=convertToNull&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
# 下面為連接池的補(bǔ)充設(shè)置,應(yīng)用到上面所有數(shù)據(jù)源中
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
# 配置獲取連接等待超時(shí)的時(shí)間
spring.datasource.maxWait=60000
# 配置間隔多久才進(jìn)行一次檢測(cè),檢測(cè)需要關(guān)閉的空閑連接,單位是毫秒
spring.datasource.timeBetweenEvictionRunsMillis=60000
# 配置一個(gè)連接在池中最小生存的時(shí)間,單位是毫秒
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
# 配置監(jiān)控統(tǒng)計(jì)攔截的filters,去掉后監(jiān)控界面sql無法統(tǒng)計(jì),'wall'用于防火墻
spring.datasource.filters=stat,wall,log4j
spring.datasource.logSlowSql=true

需要說明的是,上面配置中的filters:stat表示已經(jīng)可以使用監(jiān)控過濾器,這時(shí)結(jié)合定義一個(gè)過濾器,我們就可以用其來監(jiān)控SQL的執(zhí)行情況。

開啟Druid的SQL監(jiān)控功能
在工程中開啟監(jiān)控功能后,可以在工程應(yīng)用運(yùn)行過程中,通過Druid數(shù)據(jù)源連接池自帶SQL監(jiān)控提供的多維度數(shù)據(jù),分析出業(yè)務(wù)SQL執(zhí)行的情況,從而可以調(diào)整和優(yōu)化代碼以及SQL,方便業(yè)務(wù)開發(fā)同事調(diào)優(yōu)數(shù)據(jù)庫的訪問性能。

要達(dá)到開啟SQL監(jiān)控的效果,還需在Spring Boot工程中還實(shí)現(xiàn)Druid數(shù)據(jù)源連接池的Serlvet以及Filter,其Bean的初始化代碼如下(下面給出兩種配置方式):

第一種方式@Confing注解的配置類:

/**
 * druid 配置.
 * <p>
 * 這樣的方式不需要添加注解:@ServletComponentScan
 *
 * @author Administrator
 */
@Configuration
public class DruidConfiguration {

    /**
     * 注冊(cè)一個(gè)StatViewServlet
     *
     * @return
     */
    @Bean
    public ServletRegistrationBean DruidStatViewServle2() {
        //org.springframework.boot.context.embedded.ServletRegistrationBean提供類的進(jìn)行注冊(cè).
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        servletRegistrationBean.addUrlMappings("/druid/*");

        //添加初始化參數(shù):initParams

        //白名單:
        servletRegistrationBean.addInitParameter("allow", "127.0.0.1");
        //IP黑名單 (存在共同時(shí),deny優(yōu)先于allow) : 如果滿足deny的話提示:Sorry, you are not permitted to view this page.
        servletRegistrationBean.addInitParameter("deny", "192.168.1.73");
        //登錄查看信息的賬號(hào)密碼.
        servletRegistrationBean.addInitParameter("loginUsername", "admin");
        servletRegistrationBean.addInitParameter("loginPassword", "admin");
        //是否能夠重置數(shù)據(jù).
        servletRegistrationBean.addInitParameter("resetEnable", "false");
        return servletRegistrationBean;
    }

    /**
     * 注冊(cè)一個(gè):filterRegistrationBean
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean druidStatFilter2() {

        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());

        //添加過濾規(guī)則.
        filterRegistrationBean.addUrlPatterns("/*");

        //添加不需要忽略的格式信息.
        filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid2/*");
        return filterRegistrationBean;
    }

}

第二種方式基于注解的配置:

/**
 * druid數(shù)據(jù)源狀態(tài)監(jiān)控.
 *
 * @author Administrator
 */
@WebServlet(urlPatterns = "/druid/*",
        initParams = {
                @WebInitParam(name = "allow", value = "192.168.1.72,127.0.0.1"),// IP白名單(沒有配置或者為空,則允許所有訪問)
                @WebInitParam(name = "deny", value = "192.168.1.73"),// IP黑名單 (存在共同時(shí),deny優(yōu)先于allow)
                @WebInitParam(name = "loginUsername", value = "admin"),// 用戶名
                @WebInitParam(name = "loginPassword", value = "admin"),// 密碼
                @WebInitParam(name = "resetEnable", value = "false")// 禁用HTML頁面上的“Reset All”功能
        }
)
public class DruidStatViewServlet extends StatViewServlet {
    private static final long serialVersionUID = 1L;

}
/**
 * druid過濾器.
 *
 * @author Administrator
 */
@WebFilter(filterName = "druidWebStatFilter", urlPatterns = "/*",
        initParams = {
                @WebInitParam(name = "exclusions", value = "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*")//忽略資源
        }
)
public class DruidStatFilter extends WebStatFilter {

}

使用上面第二種方式的話,還需要在Spring Boot工程的啟動(dòng)類上添加注解:@ServletComponentScan,這樣使Spring能夠掃描到我們自己編寫的servlet和filter。

使用Druid進(jìn)行SQL監(jiān)控的效果
我們已經(jīng)配置完成了Druid的監(jiān)控,在本地運(yùn)行Spring Boot的Jar包,運(yùn)行成功后即可訪問Druid監(jiān)控界面,默認(rèn)訪問地址為:http://localhost:8080/druid/,最終的效果圖如下所示:

Login.png

可以看到了我們成功的訪問了Druid的監(jiān)控頁面,那么現(xiàn)在輸入我們?cè)贐ean初始化時(shí)候設(shè)置的用戶名、密碼(admin/admin)登錄監(jiān)控平臺(tái),進(jìn)入監(jiān)控平臺(tái)首頁,如下所示:

image.png

image.png

有了Web UI我們就可以方便的從這個(gè)UI上看到該工程部署起來后數(shù)據(jù)源初始化配置以及業(yè)務(wù)級(jí)SQL的執(zhí)行情況。

4. 總結(jié)

本文圍繞Druid數(shù)據(jù)源連接池為主題,先簡要地介紹了該連接池的功能,然后通過與業(yè)界幾款較為流行的數(shù)據(jù)源連接池進(jìn)行橫向?qū)Ρ?,分析出Druid連接池的特色和優(yōu)勢(shì)。最后通過實(shí)踐,進(jìn)一步向大家闡述如何在一個(gè)Spring Boot工程中添加Druid連接池進(jìn)行業(yè)務(wù)SQL級(jí)別的監(jiān)控。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 47,272評(píng)論 6 342
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,551評(píng)論 19 139
  • Druid的簡介 Druid是一個(gè)非常優(yōu)秀的數(shù)據(jù)庫連接池。在功能、性能、擴(kuò)展性方面,都超過其他數(shù)據(jù)庫連接池,包括D...
    xiaolyuh閱讀 5,847評(píng)論 0 16
  • 碧桃是觀賞花的桃樹品種,在我們這個(gè)地區(qū),碧桃每年二月上旬到中旬開花。今年春節(jié)正好遇到桃花開放,增加了節(jié)日的歡樂氣氛...
    碧海藍(lán)灣閱讀 2,118評(píng)論 2 2
  • 莫讓風(fēng)沙迷失了雙眼, 莫讓離別變成了遺憾, 風(fēng)的季節(jié), 雨的孤單, 誰在默默陪伴, 波浪式的生活, 誰言曾經(jīng)不堪,...
    微風(fēng)的自由閱讀 322評(píng)論 2 2

友情鏈接更多精彩內(nèi)容