1. 程式人生 > >Spring Boot 2.x基礎教程:使用國產資料庫連線池Druid

Spring Boot 2.x基礎教程:使用國產資料庫連線池Druid

上一節,我們介紹了Spring Boot在JDBC模組中自動化配置使用的預設資料來源HikariCP。接下來這一節,我們將介紹另外一個被廣泛應用的開源資料來源:Druid。

Druid是由阿里巴巴資料庫事業部出品的開源專案。它除了是一個高效能資料庫連線池之外,更是一個自帶監控的資料庫連線池。雖然HikariCP已經很優秀,但是對於國內使用者來說,可能對於Druid更為熟悉。所以,對於如何在Spring Boot中使用Druid是後端開發人員必須要掌握的基本技能。

配置Druid資料來源

這一節的實踐我們將基於《Spring Boot 2.x基礎教程:使用JdbcTemplate訪問MySQL資料庫》一文的程式碼基礎上進行。所以,讀者可以從文末的程式碼倉庫中,檢出chapter3-1

目錄來進行下面的實踐學習。

下面我們就來開始對Spring Boot專案配置Druid資料來源:

第一步:在pom.xml中引入druid官方提供的Spring Boot Starter封裝。

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.21</version>
</dependency>

第二步:在application.properties

中配置資料庫連線資訊。

Druid的配置都以spring.datasource.druid作為字首,所以根據之前的配置,稍作修改即可:

spring.datasource.druid.url=jdbc:mysql://localhost:3306/test
spring.datasource.druid.username=root
spring.datasource.druid.password=
spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver

第三步:配置Druid的連線池。

與Hikari一樣,要用好一個數據源,就要對其連線池做好相應的配置,比如下面這樣:

spring.datasource.druid.initialSize=10
spring.datasource.druid.maxActive=20
spring.datasource.druid.maxWait=60000
spring.datasource.druid.minIdle=1
spring.datasource.druid.timeBetweenEvictionRunsMillis=60000
spring.datasource.druid.minEvictableIdleTimeMillis=300000
spring.datasource.druid.testWhileIdle=true
spring.datasource.druid.testOnBorrow=true
spring.datasource.druid.testOnReturn=false
spring.datasource.druid.poolPreparedStatements=true
spring.datasource.druid.maxOpenPreparedStatements=20
spring.datasource.druid.validationQuery=SELECT 1
spring.datasource.druid.validation-query-timeout=500
spring.datasource.druid.filters=stat

關於Druid中各連線池配置的說明可查閱下面的表格:

配置 預設值 說明
name 配置這個屬性的意義在於,如果存在多個數據源,監控的時候可以通過名字來區分開來。如果沒有配置,將會生成一個名字,格式是:”DataSource-“ + System.identityHashCode(this). 另外配置此屬性至少在1.0.5版本中是不起作用的,強行設定name會出錯。詳情-點此處。
url 連線資料庫的url,不同資料庫不一樣。例如: mysql : jdbc:mysql://10.20.153.104:3306/druid2 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檢測連線是否有效。
keepAlive false (1.0.28) 連線池中的minIdle數量以內的連線,空閒時間超過minEvictableIdleTimeMillis,則會執行keepAlive操作。
timeBetweenEvictionRunsMillis 1分鐘(1.0.14) 有兩個含義: 1) Destroy執行緒會檢測連線的間隔時間,如果連線空閒時間大於等於minEvictableIdleTimeMillis則關閉物理連線。 2) testWhileIdle的判斷依據,詳細看testWhileIdle屬性的說明
numTestsPerEvictionRun 30分鐘(1.0.14) 不再使用,一個DruidDataSource只支援一個EvictionRun
minEvictableIdleTimeMillis 連線保持空閒而不被驅逐的最小時間
connectionInitSqls 物理連線初始化的時候執行的sql
exceptionSorter 根據dbType自動識別 當資料庫丟擲一些不可恢復的異常時,拋棄連線
filters 屬性型別是字串,通過別名的方式配置擴充套件外掛,常用的外掛有: 監控統計用的filter:stat 日誌用的filter:log4j 防禦sql注入的filter:wall
proxyFilters 型別是List<com.alibaba.druid.filter.Filter>,如果同時配置了filters和proxyFilters,是組合關係,並非替換關係

到這一步,就已經完成了將Spring Boot的預設資料來源HikariCP切換到Druid的所有操作。

配置Druid監控

既然用了Druid,那麼對於Druid的監控功能怎麼能不用一下呢?下面就來再進一步做一些配置,來啟用Druid的監控。

第一步:在pom.xml中引入spring-boot-starter-actuator模組

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

第二步:在application.properties中新增Druid的監控配置。

spring.datasource.druid.stat-view-servlet.enabled=true
spring.datasource.druid.stat-view-servlet.url-pattern=/druid/*
spring.datasource.druid.stat-view-servlet.reset-enable=true
spring.datasource.druid.stat-view-servlet.login-username=admin
spring.datasource.druid.stat-view-servlet.login-password=admin

上面的配置主要用於開啟stat監控統計的介面以及監控內容的相關配置,具體釋意如下:

  • spring.datasource.druid.stat-view-servlet.url-pattern:訪問地址規則
  • spring.datasource.druid.stat-view-servlet.reset-enable:是否允許清空統計資料
  • spring.datasource.druid.stat-view-servlet.login-username:監控頁面的登入賬戶
  • spring.datasource.druid.stat-view-servlet.login-password:監控頁面的登入密碼

第三步:針對之前實現的UserService內容,我們建立一個Controller來通過介面去呼叫資料訪問操作:

@Data
@AllArgsConstructor
@RestController
public class UserController {

    private UserService userService;

    @PostMapping("/user")
    public int create(@RequestBody User user) {
        return userService.create(user.getName(), user.getAge());
    }

    @GetMapping("/user/{name}")
    public List<User> getByName(@PathVariable String name) {
        return userService.getByName(name);
    }

    @DeleteMapping("/user/{name}")
    public int deleteByName(@PathVariable String name) {
        return userService.deleteByName(name);
    }

    @GetMapping("/user/count")
    public int getAllUsers() {
        return userService.getAllUsers();
    }

    @DeleteMapping("/user/all")
    public int deleteAllUsers() {
        return userService.deleteAllUsers();
    }

}

第四步:完成上面所有配置之後,啟動應用,訪問Druid的監控頁面http://localhost:8080/druid/,可以看到如下登入頁面:

輸入上面spring.datasource.druid.stat-view-servlet.login-usernamespring.datasource.druid.stat-view-servlet.login-password配置的登入賬戶與密碼,就能看到如下監控頁面:

進入到這邊時候,就可以看到對於應用端而言的各種監控資料了。這裡講解幾個最為常用的監控頁面:

資料來源:這裡可以看到之前我們配置的資料庫連線池資訊以及當前使用情況的各種指標。

SQL監控:該資料來源中執行的SQL語句極其統計資料。在這個頁面上,我們可以很方便的看到當前這個Spring Boot都執行過哪些SQL,這些SQL的執行頻率和執行效率也都可以清晰的看到。如果你這裡沒看到什麼資料?別忘了我們之前建立了一個Controller,用這些介面可以觸發UserService對資料庫的操作。所以,這裡我們可以通過呼叫介面的方式去觸發一些操作,這樣SQL監控頁面就會產生一些資料:

圖中監控項上,執行時間、讀取行數、更新行數都通過區間分佈的方式表示,將耗時分佈成8個區間:

  • 0 - 1 耗時0到1毫秒的次數
  • 1 - 10 耗時1到10毫秒的次數
  • 10 - 100 耗時10到100毫秒的次數
  • 100 - 1,000 耗時100到1000毫秒的次數
  • 1,000 - 10,000 耗時1到10秒的次數
  • 10,000 - 100,000 耗時10到100秒的次數
  • 100,000 - 1,000,000 耗時100到1000秒的次數
  • 1,000,000 - 耗時1000秒以上的次數

記錄耗時區間的發生次數,通過區分分佈,可以很方便看出SQL執行的極好、普通和極差的分佈。 耗時區分分佈提供了“執行+RS時分佈”,是將執行時間+ResultSet持有時間合併監控,這個能方便診斷返回行數過多的查詢。

SQL防火牆:該頁面記錄了與SQL監控不同維度的監控資料,更多用於對錶訪問維度、SQL防禦維度的統計。

該功能資料記錄的統計需要在spring.datasource.druid.filters中增加wall屬性才會進行記錄統計,比如這樣:

spring.datasource.druid.filters=stat,wall

注意:這裡的所有監控資訊是對這個應用例項的資料來源而言的,而並不是資料庫全域性層面的,可以視為應用層的監控,不可能作為中介軟體層的監控。

程式碼示例

本文的相關例子可以檢視下面倉庫中的chapter3-3目錄:

  • Github:https://github.com/dyc87112/SpringBoot-Learning/
  • Gitee:https://gitee.com/didispace/SpringBoot-Learning/

如果您覺得本文不錯,歡迎Star支援,您的關注是我堅持的動力!

歡迎關注我的公眾號:程式猿DD,獲得獨家整理的學習資源和日常乾貨推送。
如果您對我的專題內容感興趣,也可以關注我的部落格:didispace.com