SpringBoot學習之整合Druid的簡單應用

一、Druid介紹

Druid簡介

Druid是目前Java語言中最好的資料庫連接池之一。結合了 C3P0、DBCP 等 DB 池的優點,同時加入了日誌監控。Druid 是一個分散式的、支援實時多維 OLAP 分析的數據處理系統。它既支援高速的數據實時攝入處理,也支援實時且靈活的多維數據分析查詢。

Druid已經在阿里巴巴部署了超過600個應用,經過生產環境大規模部署的嚴苛考驗。Spring Boot 2.0 以上默認使用 Hikari 數據源,可以說 Hikari 與 Driud 都是當前 Java Web 上最優秀的數據源。

Druid特性

支援

  • 亞秒響應的互動式查詢,支援較高並發。
  • 支援實時導入,導入即可被查詢,支援高並發導入。
  • 採用分散式 shared-nothing 的架構,可以擴展到PB級。
  • 支援聚合函數,count 和 sum,以及使用 javascript 實現自定義 UDF。
  • 支援複雜的 Aggregator,近似查詢的 Aggregator 例如 HyperLoglog 以及 Yahoo 開源的 DataSketches。
  • 支援Groupby,Select,Search查詢。
  • 不支援大表之間的Join,但其 lookup 功能滿足和維度表的 Join。

不支援

  • 不支援精確去重
  • 不支援 Join(只能進行 semi-join)
  • 不支援根據主鍵的單條記錄更新

Druid下載

  1. maven中央倉庫: //central.maven.org/maven2/com/alibaba/druid/
  2. 源程式碼倉庫地址: //github.com/alibaba/druid

Druid可以做什麼

  1. 可以監控資料庫訪問性能,Druid內置提供了一個功能強大的StatFilter插件,能夠詳細統計SQL的執行性能,這對於線上分析資料庫訪問性能有幫助。

  2. 替換DBCP和C3P0。Druid提供了一個高效、功能強大、可擴展性好的資料庫連接池。

  3. 資料庫密碼加密。直接把資料庫密碼寫在配置文件中,這是不好的行為,容易導致安全問題。DruidDruiver和DruidDataSource都支援PasswordCallback。

  4. SQL執行日誌,Druid提供了不同的LogFilter,能夠支援Common-Logging、Log4j和JdkLog,你可以按需要選擇相應的LogFilter,監控你應用的資料庫訪問情況。

二、Druid在SpringBoot中的整合

配置Druid數據源

這裡基於SpringBoot 2.3.2、IntelliJ IDEA開發工具、Maven 3.6.3、Mysql 8.0.20

1.在 Spring Boot 項目中的Pom.xml文件中加入druid-spring-boot-starter依賴

<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>druid-spring-boot-starter</artifactId>
   <version>1.1.17</version>
</dependency>
<!-- log4j日誌 -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

2.添加application的配置項,這裡使用yaml文件格式

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 970628
    # 切換Druid數據源
    type: com.alibaba.druid.pool.DruidDataSource

    #Spring Boot 默認是不注入這些屬性值的,需要自己綁定
    #druid 數據源專有配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true

注意:

  1. url中在mysql的8版本以上的可能需要設置時區: serverTimezone=UTC
  2. driver-class-name資料庫驅動,如果是mysql8版本以上的使用 com.mysql.cj.jdbc.Driver,低版本的使用 com.mysql.jdbc.Driver
  3. type屬性是切換數據源為Druid,SpringBoot 2.0以上默認的數據源為 com.zaxxer.hikari.HikariDataSource

這只是部分屬性配置,下面是常用的其他配置項,可以根據情況選擇。

配置 預設值 說明
name 配置這個屬性的意義在於,如果存在多個數據源,監控的時候
可以通過名字來區分開來。如果沒有配置,將會生成一個名字,
格式是:」DataSource-」 + System.identityHashCode(this)
jdbcUrl 連接資料庫的url,不同資料庫不一樣。例如:
mysql : jdbc:mysql://10.20.153.104:3306/druid2
oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnauto
username 連接資料庫的用戶名
password 連接資料庫的密碼。如果你不希望密碼直接寫在配置文件中,
可以使用ConfigFilter。詳細看這裡:
//github.com/alibaba/druid/wiki/使用ConfigFilter
driverClassName driverClassName 這一項可配可不配,如果不配置druid會根據url自動識別dbType,
然後選擇相應的driverClassName
initialSize 0 初始化時建立物理連接的個數。初始化發生在顯示調用init方法,
或者第一次getConnection時
maxActive 8 最大連接池數量
maxIdle 8 已經不再使用,配置了也沒效果
minIdle 最小連接池數量
maxWait 獲取連接時最大等待時間,單位毫秒。配置了maxWait之後,
預設啟用公平鎖,並發效率會有所下降,
如果需要可以通過配置useUnfairLock屬性為true使用非公平鎖。
poolPreparedStatements false 是否快取preparedStatement,也就是PSCache。
PSCache對支援游標的資料庫性能提升巨大,比如說oracle。
在mysql5.5以下的版本中沒有PSCache功能,建議關閉掉。
5.5及以上版本有PSCache,建議開啟。
maxOpenPreparedStatements -1 要啟用PSCache,必須配置大於0,當大於0時,
poolPreparedStatements自動觸發修改為true。
在Druid中,不會存在Oracle下PSCache佔用記憶體過多的問題,
可以把這個數值配置大一些,比如說100
validationQuery 用來檢測連接是否有效的sql,要求是一個查詢語句。
如果validationQuery為null,testOnBorrow、testOnReturn、
testWhileIdle都不會其作用。
testOnBorrow true 申請連接時執行validationQuery檢測連接是否有效,
做了這個配置會降低性能。
testOnReturn false 歸還連接時執行validationQuery檢測連接是否有效,
做了這個配置會降低性能
testWhileIdle false 建議配置為true,不影響性能,並且保證安全性。
申請連接的時候檢測,如果空閑時間大於
timeBetweenEvictionRunsMillis,
執行validationQuery檢測連接是否有效
timeBetweenEvictionRunsMillis 有兩個含義:
1) Destroy執行緒會檢測連接的間隔時間
2) testWhileIdle的判斷依據,詳細看testWhileIdle屬性的說明
connectionInitSqls 物理連接初始化的時候執行的sql
exceptionSorter 根據dbType自動識別 當資料庫拋出一些不可恢復的異常時,拋棄連接
filters 屬性類型是字元串,通過別名的方式配置擴展插件
proxyFilters 類型是List<com.alibaba.druid.filter.Filter>,
如果同時配置了filters和proxyFilters,
是組合關係,並非替換關係

3.添加 DruidDataSource 組件到容器中,並綁定屬性

在SpringBoot中需要自定義一個配置類進行屬性賦值

package com.kuang.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration
public class DruidConfig {

    /*
       將自定義的 Druid數據源添加到容器中,不再讓 Spring Boot 自動創建
       綁定全局配置文件中的 druid 數據源屬性到 com.alibaba.druid.pool.DruidDataSource從而讓它們生效
       @ConfigurationProperties(prefix = "spring.datasource"):作用就是將 全局配置文件中
       前綴為 spring.datasource的屬性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名參數中
     */
    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    public DataSource druidDataSource() {
        return new DruidDataSource();
    }

}

4.編寫測試類驗證是否生效

測試之前保證資料庫的用戶名及密碼正確及資料庫連接字元串拼寫正確

package com.tioxy;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

@SpringBootTest
class SpringBootDataApplicationTests {
    @Autowired
    DataSource dataSource;

    @Test
    void contextLoads() throws SQLException {
        // 查看一下默認的數據源
        System.out.println(dataSource.getClass());
        // 獲得資料庫鏈接
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
        connection.close();
    }

}

測試結果

配置Druid數據源監控

Druid 的監控主要有兩點,業務查詢情況和平台運行情況。前者主要包括 datasource 的查詢量、查詢耗時、網路流量等;後者主要包括各個服務的 gc 情況、cpu 和記憶體使用情況、空閑 Jetty 執行緒數等。

配置步驟如下:

1.添加application的配置項

在原來的配置基礎上添加數據源監控配置項

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 970628
    # 切換Druid數據源
    type: com.alibaba.druid.pool.DruidDataSource

    #Spring Boot 默認是不注入這些屬性值的,需要自己綁定
    #druid 數據源專有配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true

    #配置監控統計攔截的filters,stat:監控統計、log4j:日誌記錄、wall:防禦sql注入
    #如果允許時報錯  java.lang.ClassNotFoundException: org.apache.log4j.Priority
    #則導入 log4j 依賴即可,Maven 地址://mvnrepository.com/artifact/log4j/log4j
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

2.配置Druid數據監控登錄的帳號密碼

因為Druid內置了數據監控的可視化介面,我們可以設置其登錄的帳號及密碼,這樣就可以直觀的進行各項業務查詢和平台運行監控情況。

我們原來在SSM中配置頁面需要用到servlet,springBoot 內置了servlet容器,所以沒有web.xml,使用這種的配置類,用bean的方式註冊到容器中,所以在配置類添加自定義servlet方法。

//配置 Druid 監控管理後台的Servlet;
//內置 Servlet 容器時沒有web.xml文件,所以使用 Spring Boot 的註冊 Servlet 方式
@Bean
public ServletRegistrationBean statViewServlet() {
    ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");

    // 這些參數可以在 com.alibaba.druid.support.http.StatViewServlet 
    // 的父類 com.alibaba.druid.support.http.ResourceServlet 中找到
    Map<String, String> initParams = new HashMap<>();
    initParams.put("loginUsername", "admin"); //後台管理介面的登錄帳號
    initParams.put("loginPassword", "123456"); //後台管理介面的登錄密碼

    //後台允許誰可以訪問
    //initParams.put("allow", "localhost"):表示只有本機可以訪問
    //initParams.put("allow", ""):為空或者為null時,表示允許所有訪問
    initParams.put("allow", "");
    //deny:Druid 後台拒絕誰訪問
    //initParams.put("kuangshen", "192.168.1.20");表示禁止此ip訪問

    //設置初始化參數
    bean.setInitParameters(initParams);
    return bean;
}

啟動測試運行,檢查配置是否成功

運行後輸入地址://localhost:8080/druid/login.html

進入到Druid的後台登錄頁面

輸入配置好的帳號密碼,點擊登錄,即可進入控制台頁面

3.(可選)配置Druid過濾器

在實際的開發中,此項根據實際的業務和要求進行配置

同樣的在Druid配置類中添加一下方法:

//配置 Druid 監控 之  web 監控的 filter
//WebStatFilter:用於配置Web和Druid數據源之間的管理關聯監控統計
@Bean
public FilterRegistrationBean webStatFilter() {
    FilterRegistrationBean bean = new FilterRegistrationBean();
    bean.setFilter(new WebStatFilter());

    //exclusions:設置哪些請求進行過濾排除掉,從而不進行統計
    Map<String, String> initParams = new HashMap<>();
    initParams.put("exclusions", "*.js,*.css,/druid/*,/jdbc/*");
    bean.setInitParameters(initParams);

    //"/*" 表示過濾所有請求
    bean.setUrlPatterns(Arrays.asList("/*"));
    return bean;
}

以上便是SpringBoot整合Druid的簡單使用,這只是入門配置,如後續根據實際的業務進行業務增加及調整。

文章引用:
狂神說JAVA之SpringBoot整合Druid課程學習筆記