天天看點

springboot hikari連接配接不釋放_芋道 Spring Boot 資料庫連接配接池入門1. 概述2. HikariCP 單資料源3. HikariCP 多資料源4. Druid 單資料源5. Druid 多資料源666. 彩蛋

點選上方“芋道源碼”,選擇“設為星标”

做積極的人,而不是積極廢人!

源碼精品專欄

  • 原創 | Java 2020 超神之路,很肝~
  • 中文詳細注釋的開源項目
  • RPC 架構 Dubbo 源碼解析
  • 網絡應用架構 Netty 源碼解析
  • 消息中間件 RocketMQ 源碼解析
  • 資料庫中間件 Sharding-JDBC 和 MyCAT 源碼解析
  • 作業排程中間件 Elastic-Job 源碼解析
  • 分布式事務中間件 TCC-Transaction 源碼解析
  • Eureka 和 Hystrix 源碼解析
  • Java 并發源碼
摘要: 原創出處 http://www.iocoder.cn/Spring-Boot/datasource-pool/ 「芋道源碼」歡迎轉載,保留摘要,謝謝!
  • 1. 概述
  • 2. HikariCP 單資料源
  • 3. HikariCP 多資料源
  • 4. Druid 單資料源
  • 5. Druid 多資料源
  • 666. 彩蛋

本文在提供完整代碼示例,可見 https://github.com/YunaiV/SpringBoot-Labs 的 lab-19 目錄。

原創不易,給點個 Star 嘿,一起沖鴨!

1. 概述

在我們的項目中,資料庫連接配接池基本是必不可少的元件。在目前資料庫連接配接池的選型中,主要是

  • Druid ,為監控而生的資料庫連接配接池。
  • HikariCP ,号稱性能最好的資料庫連接配接池。

至于怎麼選擇,兩者都非常優秀,不用過多糾結。

  • Spring Boot 2.X 版本,預設采用 HikariCP 。
  • 阿裡大規模采用 Druid 。

當然,如下有一些資料,胖友可以閱讀參考:

  • 《Druid 連接配接池介紹》
  • 《為什麼 HikariCP 被号稱為性能最好的 Java 資料庫連接配接池,如何配置使用》
  • 《alibaba/druid pool analysis》 ,一個小小的“撕逼”。

下面,我們來進行 HikariCP 和 Druid 的入門,會配置單資料源和多資料源情況下的連接配接池。

2. HikariCP 單資料源

示例代碼對應倉庫:lab-19-datasource-pool-hikaricp-single 。

在本小節,我們會使用配置一個資料源的 HikariCP 連接配接池。

艿艿:推薦入門後,可以看看 HikariCP 的文檔:https://github.com/brettwooldridge/HikariCP/wiki 。

2.1 引入依賴

pom.xml

檔案中,引入相關依賴。

  • 無需主動引入 HikariCP 的依賴。因為在 Spring Boot 2.X 中,

    spring-boot-starter-jdbc

    預設引入

    com.zaxxer.HikariCP

    依賴。

2.2 應用配置檔案

application.yml

中,添加 HikariCP 配置,如下:

  • spring.datasource

    配置項下,我們可以添加資料源的通用配置。
  • spring.datasource.hikari

    配置項下,我們可以添加 HikariCP 連接配接池的自定義配置。然後

    DataSourceConfiguration.Hikari

    會自動化配置 HikariCP 連接配接池。

HikariCP 更多配置項,可以看看如下表格:s

FROM 《HikariCP 連接配接池及其在 Spring Boot 中的配置》
配置項 描述 構造器預設值 預設配置validate之後的值 validate重置
autoCommit 自動送出從池中傳回的連接配接 true true -
connectionTimeout 等待來自池的連接配接的最大毫秒數 SECONDS.toMillis(30) = 30000 30000 如果小于250毫秒,則被重置回30秒
idleTimeout 連接配接允許在池中閑置的最長時間 MINUTES.toMillis(10) = 600000 600000 如果idleTimeout+1秒>maxLifetime 且 maxLifetime>0,則會被重置為0(代表永遠不會退出);如果idleTimeout!=0且小于10秒,則會被重置為10秒
maxLifetime 池中連接配接最長生命周期 MINUTES.toMillis(30) = 1800000 1800000 如果不等于0且小于30秒則會被重置回30分鐘
connectionTestQuery 如果您的驅動程式支援JDBC4,我們強烈建議您不要設定此屬性 null null -
minimumIdle 池中維護的最小空閑連接配接數 -1 10 minIdle<0或者minIdle>maxPoolSize,則被重置為maxPoolSize
maximumPoolSize 池中最大連接配接數,包括閑置和使用中的連接配接 -1 10 如果maxPoolSize小于1,則會被重置。當minIdle<=0被重置為DEFAULT_POOL_SIZE則為10;如果minIdle>0則重置為minIdle的值
metricRegistry 該屬性允許您指定一個 Codahale / Dropwizard

MetricRegistry

的執行個體,供池使用以記錄各種名額
null null -
healthCheckRegistry 該屬性允許您指定池使用的Codahale / Dropwizard HealthCheckRegistry的執行個體來報告目前健康資訊 null null -
poolName 連接配接池的使用者定義名稱,主要出現在日志記錄和JMX管理控制台中以識别池和池配置 null HikariPool-1 -
initializationFailTimeout 如果池無法成功初始化連接配接,則此屬性控制池是否将

fail fast

1 1 -
isolateInternalQueries 是否在其自己的事務中隔離内部池查詢,例如連接配接活動測試 false false -
allowPoolSuspension 控制池是否可以通過JMX暫停和恢複 false false -
readOnly 從池中擷取的連接配接是否預設處于隻讀模式 false false -
registerMbeans 是否注冊JMX管理Bean(

MBeans

)
false false -
catalog 為支援

catalog

概念的資料庫設定預設

catalog

driver default null -
connectionInitSql 該屬性設定一個SQL語句,在将每個新連接配接建立後,将其添加到池中之前執行該語句。 null null -
driverClassName HikariCP将嘗試通過僅基于jdbcUrl的DriverManager解析驅動程式,但對于一些較舊的驅動程式,還必須指定driverClassName null null -
transactionIsolation 控制從池傳回的連接配接的預設事務隔離級别 null null -
validationTimeout 連接配接将被測試活動的最大時間量 SECONDS.toMillis(5) = 5000 5000 如果小于250毫秒,則會被重置回5秒
leakDetectionThreshold 記錄消息之前連接配接可能離開池的時間量,表示可能的連接配接洩漏 如果大于0且不是單元測試,則進一步判斷:(leakDetectionThreshold < SECONDS.toMillis(2) or (leakDetectionThreshold > maxLifetime && maxLifetime > 0),會被重置為0 . 即如果要生效則必須>0,而且不能小于2秒,而且當maxLifetime > 0時不能大于maxLifetime
dataSource 這個屬性允許你直接設定資料源的執行個體被池包裝,而不是讓HikariCP通過反射來構造它 null null -
schema 該屬性為支援模式概念的資料庫設定預設模式 driver default null -
threadFactory 此屬性允許您設定将用于建立池使用的所有線程的java.util.concurrent.ThreadFactory的執行個體。 null null -
scheduledExecutor 此屬性允許您設定将用于各種内部計劃任務的java.util.concurrent.ScheduledExecutorService執行個體 null null -

2.3 Application

建立

Application.java

類,配置

@SpringBootApplication

注解即可。代碼如下:

通過實作 CommandLineRunner 接口,應用啟動完成後,回調

#run(String... args)

方法,輸出下 Connection 資訊。執行日志如下:

  • 可以看到,HikariDataSource 成功初始化。

3. HikariCP 多資料源

示例代碼對應倉庫:lab-19-datasource-pool-hikaricp-multiple 。

在本小節,我們會使用配置兩個資料源的 HikariCP 連接配接池。

3.1 引入依賴

和 「2.1 引入依賴」 是一緻。

3.2 應用配置檔案

application.yml

中,添加 HikariCP 配置,如下:

  • 我們在

    spring.datasource

    配置項下,定義了

    orders

    users

    兩個資料源的配置。而每個資料源的配置,和我們在 「2.2 應用配置檔案」 是一緻的。

3.3 資料源配置類

3.3.1 錯誤的示例

在網上,我們會看到這樣配置多個資料源的配置類。代碼如下:

  • 實際上,這樣做的話,在部分場景下,會存在問題,這是為什麼呢?
  • 我們先來了解這段程式的用途。以

    #ordersDataSource()

    方法為例子:
    • DataSourceBuilder.create().build()

      代碼段,會建立一個 DataSource 資料源。
    • 搭配上

      @Bean(name = "ordersDataSource")

      注解,會建立一個名字為

      "ordersDataSource"

      的 DataSource Bean 。這裡,我們使用 HikariCP ,是以傳回的是 HikariDataSource Bean 。
    • @ConfigurationProperties(prefix = "spring.datasource.orders")

      注解,會将

      "spring.datasource.orders"

      配置項,逐個屬性指派給 DataSource Bean 。
  • 看起來貌似沒問題,但是如果每個資料源如果有 HikariCP 的

    "hikari"

    自定義配置項時,它的自定義配置項無法設定到 HikariDataSource Bean 中。因為,

    "spring.datasource.orders.hikari"

    "spring.datasource.orders"

    的第二層屬性。而 HikariDataSource 的配置屬性在第一層,這就導緻無法正确的設定。

雖然存在該問題,但是大多數項目,我們并不會自定義 HikariCP 的

"hikari"

配置項,是以這個問題就偷偷藏起來,**“不存在”**了。

3.3.2 正确的示例

當然,作為入門的示例,艿艿還是希望提供正确的做法。

cn.iocoder.springboot.lab19.datasourcepool.config

包路徑下,我們會建立 DataSourceConfig 配置類。代碼如下:

  • 這塊代碼,我們是參考 Spring Boot

    DataSourceConfiguration.Hikari

    配置類來實作的。
  • #ordersDataSourceProperties()

    方法,建立

    "orders"

    資料源的 DataSourceProperties 配置對象。
    • @Primary

      注解,保證項目中有一個主的 DataSourceProperties Bean 。
    • new DataSourceProperties()

      代碼段,會建立一個 DataSourceProperties 資料源的配置對象。
    • 搭配上

      @Bean(name = "ordersDataSourceProperties")

      注解,會建立一個名字為

      "ordersDataSourceProperties"

      的 DataSourceProperties Bean 。
    • @ConfigurationProperties(prefix = "spring.datasource.orders")

      注解,會将

      "spring.datasource.orders"

      配置項,逐個屬性指派給 DataSourceProperties Bean 。
  • #ordersDataSource()

    方法,建立

    orders

    資料源。
    • <1.1>

      處,調用

      #ordersDataSourceProperties()

      方法,獲得

      orders

      資料源的 DataSourceProperties 。
    • <1.2>

      處,調用

      #createHikariDataSource(DataSourceProperties properties)

      方法,建立 HikariDataSource 對象。這樣,

      "spring.datasource.orders"

      配置項,逐個屬性指派給 HikariDataSource Bean 。
    • 搭配上

      @Bean(name = "ordersDataSource")

      注解,會建立一個名字為

      "ordersDataSource"

      的 HikariDataSource Bean 。
    • @ConfigurationProperties(prefix = "spring.datasource.orders.hikari")

      注解,會将 HikariCP 的

      "spring.datasource.orders.hikari"

      自定義配置項,逐個屬性指派給 HikariDataSource Bean 。
  • users

    資料源的配置,同上,就不重複解釋了。

3.4 Application

建立

Application.java

類,配置

@SpringBootApplication

注解即可。代碼如下:

執行日志如下:

  • 可以看到,兩個 HikariDataSource 成功初始化。

多資料源和 JPA、MyBatis、JdbcTemplate 的內建,可以看看 《芋道 Spring Boot 多資料源(讀寫分離)入門》 文章。

4. Druid 單資料源

示例代碼對應倉庫:lab-19-datasource-pool-druid-single 。

在本小節,我們會使用配置一個資料源的 Druid 連接配接池。并簡單看看 Druid 的監控功能。

艿艿:推薦入門後,可以看看 Druid 的文檔:https://github.com/alibaba/druid/wiki/ 。

4.1 引入依賴

pom.xml

檔案中,引入相關依賴。

具體每個依賴的作用,胖友自己認真看下艿艿添加的所有注釋噢。S

4.2 應用配置檔案

application.yml

中,添加 Druid 配置,如下:

  • spring.datasource

    配置項,設定 Spring 資料源的通用配置。其中,

    spring.datasource.type

    配置項,需要主動設定使用 DruidDataSource 。因為預設情況下,

    spring-boot-starter-jdbc

    的 DataSourceBuilder 會按照

    DATA_SOURCE_TYPE_NAMES

    的順序,嘗試推斷資料源的類型。
  • spring.datasource.druid

    配置項,設定 Druid 連接配接池的自定義配置。然後 DruidDataSourceAutoConfigure 會自動化配置 Druid 連接配接池。
    • 在 《Druid —— 配置屬性》 和 《DruidDataSource 配置屬性清單》 下,提供了各種 Druid 的配置項,胖友可以自己看看。
    • filter.stat

      配置項,我們配置了 Druid StatFilter ,用于統計監控資訊。對應文檔 《Druid —— 配置_StatFilter》 。要注意,StatFilter 并不是我們說的

      javax.servlet.Filter

      ,而是 Druid 提供的 Filter 拓展機制。
    • filter.stat-view-servlet

      配置項,我們配置了 Druid StatViewServlet ,用于提供監控資訊的展示的 html 頁面和 JSON API 。對應文檔 《Druid —— 配置_StatViewServlet 配置》 。StatViewServlet 就是我們說的

      javax.servlet.Filter

4.3 Application

建立

Application.java

類,配置

@SpringBootApplication

注解即可。代碼如下:

執行日志如下:

  • 可以看到,DruidDataSource 成功初始化。

4.4 監控功能

因為我們在 「4.2 應用配置中」 中,做了如下操作:

  • 通過

    spring.datasource.filter.stat

    配置了 StatFilter ,統計監控資訊。
  • 通過

    spring.datasource.filter.stat-view-servlet

    配置了 StatViewServlet ,提供監控資訊的展示的 html 頁面和 JSON API 。

是以我們在啟動項目後,通路

http://127.0.0.1:8080/druid

位址,可以看到監控 html 頁面。如下圖所示:

springboot hikari連接配接不釋放_芋道 Spring Boot 資料庫連接配接池入門1. 概述2. HikariCP 單資料源3. HikariCP 多資料源4. Druid 單資料源5. Druid 多資料源666. 彩蛋
  • 在界面的頂部,提供了資料源、SQL 監控、SQL 防火牆等等功能。
  • 每個界面上,可以通過 View JSON API 獲得資料的來源。同時,我們可以在 JSON API(

    http://127.0.0.1:8080/druid/api.html

    ) 菜單對應的界面中,看到 StatViewServlet 内置的監控資訊的 JSON API 清單。
  • 因為監控資訊是存儲在 JVM 記憶體中,在 JVM 程序重新開機時,資訊将會丢失。如果我們希望持久化到 MySQL、Elasticsearch、HBase 等存儲器中,可以通過 StatViewServlet 提供的 JSON API 接口,采集監控資訊。另外,有個 druid-aggregated-monitor 開源項目,提供了 集中監控分布式服務中的 Druid 連接配接池的方案和思路。
  • 如果 StatViewServlet 提供的 JSON API 接口,無法滿足我們的訴求,我們可以通過自定義 API 接口,使用 DruidStatManagerFacade 獲得監控資訊。使用示例 DruidStatController 代碼如下:
    • 當然,絕大多數情況下,我們并不需要做這方面的拓展。

5. Druid 多資料源

示例代碼對應倉庫:lab-19-datasource-pool-druid-multiple 。

在本小節,我們會使用配置兩個資料源的 Druid 連接配接池。

5.1 引入依賴

和 「4.1 引入依賴」 是一緻。

5.2 應用配置

application.yml

中,添加 Druid 配置,如下:

  • 不同于我們在 「3.2 應用配置檔案」 中,我們将 Druid 的自定義配置,和

    url

    driver-class-name

    等資料源的通用配置放在同一級,這樣後續我們隻需要使用

    @ConfigurationProperties(prefix = "spring.datasource.orders")

    的方式,就能完成 DruidDataSource 的配置屬性設定。
  • spring.datasource.druid

    配置項下,我們還是配置了

    filter.stat

    stat-view-servlet

    配置項,用于 Druid 監控功能。

5.3 資料源配置類

cn.iocoder.springboot.lab19.datasourcepool.config

包路徑下,我們會建立 DataSourceConfig 配置類。代碼如下:

  • 因為我們在 「5.2 應用配置」 中,将 Druid 自定義的配置項,和資料源的通用配置放在了同一級,是以我們隻需使用

    @ConfigurationProperties(prefix = "spring.datasource.orders")

    這樣的方式即可。
  • 當然,「3.3.2 正确的示例」 也是可以這麼做的。實際情況下,比較推薦本小節的方式。

5.4 Application

建立

Application.java

類,配置

@SpringBootApplication

注解即可。代碼如下:

執行日志如下:

  • 可以看到,兩個 DruidDataSource 成功初始化。

5.5 監控功能

和 「4.4 監控功能」 一緻。

不過呢,我們在監控頁面上,可以看到兩個 Druid 資料庫連接配接池。

666. 彩蛋

艿艿:咳咳咳,瞎哔哔了一些内容,可以選擇不看。😜

艿艿在星球裡,做了一波目前在使用的連接配接池的調查,大概比例是 Druid : HikariCP 為 2:1 左右。猜測随着 Spring Boot 2.X 逐漸普及之後,HikariCP 有一定幾率反超 Druid 。

雖然說,HikariCP 沒有直接提供監控功能,但是可以使用 Prometheus 采集 Spring Boot Metrics 的資料,後續使用 Grafana 制作儀表盤。目前,已經有 Spring Boot HikariCP / JDBC 可以直接使用。具體怎麼做,胖友可以看看 《Spring Boot 中使用 HikariCP 連接配接池》 文章。

Druid 的 Issues 3047 中,也有人提出,是否能夠提供 Druid 接入 Prometheus 統一監控的訴求。Druid 目前暫時不支援,不過有聰慧的胖友,提出了使用 Prometheus jmx_exporter 的方式,将 Druid 實作的 JMX 格式的名額暴露出來,提供給 Prometheus 采集監控資訊。

在編寫本文的過程中,無意中看到 Druid 文檔中提到,曾經想試驗性的提供 分庫分表 的功能,而艿艿的記憶中,Sharding-JDBC 曾經也想開發資料庫連接配接池的功能。大體在 DataSource 資料源上做拓展的中間件,可能都不甘于僅僅隻覆寫一塊需求,而是希望成為一站式的資料庫中間件。立個 Flag ,ShardingSphere 可能會提供資料庫連接配接池的元件。

旁白君:Sharding-JDBC 是 ShardingSphere 在 JDBC 層面提供的分庫分表元件。當然,不僅僅提供分庫分表的功能,也提供讀寫分離、資料脫敏、分布式事務等等功能。

如果胖友工作的比較早,一定還接觸過其它連接配接池。例如說,c3p0、dbcp、BoneCP 等等。資料庫連接配接池的發展過程,是個非常有意思的曆史。感興趣的胖友,可以看看 《大話資料庫連接配接池簡史,你都用過幾個?》 一文,江湖味十足~

可能胖友會比較糾結,是否要去自定義連接配接池的配置呢?一般情況下,預設的配置基本能夠滿足項目的基本要求,不需要特别刻意去修改。當然,這裡推薦看兩篇文章:

  • 《DruidDataSource 配置》 ,Druid 官方提供了通用的配置。
  • 《Druid 連接配接池推薦配置》 ,某公司的内部實踐。

歡迎加入我的知識星球,一起探讨架構,交流源碼。加入方式,長按下方二維碼噢:

springboot hikari連接配接不釋放_芋道 Spring Boot 資料庫連接配接池入門1. 概述2. HikariCP 單資料源3. HikariCP 多資料源4. Druid 單資料源5. Druid 多資料源666. 彩蛋

已在知識星球更新源碼解析如下:

springboot hikari連接配接不釋放_芋道 Spring Boot 資料庫連接配接池入門1. 概述2. HikariCP 單資料源3. HikariCP 多資料源4. Druid 單資料源5. Druid 多資料源666. 彩蛋
springboot hikari連接配接不釋放_芋道 Spring Boot 資料庫連接配接池入門1. 概述2. HikariCP 單資料源3. HikariCP 多資料源4. Druid 單資料源5. Druid 多資料源666. 彩蛋
springboot hikari連接配接不釋放_芋道 Spring Boot 資料庫連接配接池入門1. 概述2. HikariCP 單資料源3. HikariCP 多資料源4. Druid 單資料源5. Druid 多資料源666. 彩蛋
springboot hikari連接配接不釋放_芋道 Spring Boot 資料庫連接配接池入門1. 概述2. HikariCP 單資料源3. HikariCP 多資料源4. Druid 單資料源5. Druid 多資料源666. 彩蛋

最近更新《芋道 SpringBoot 2.X 入門》系列,已經 20 餘篇,覆寫了 MyBatis、Redis、MongoDB、ES、分庫分表、讀寫分離、SpringMVC、Webflux、權限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能測試等等内容。

提供近 3W 行代碼的 SpringBoot 示例,以及超 4W 行代碼的電商微服務項目。

擷取方式:點“在看”,關注公衆号并回複 666 領取,更多内容陸續奉上。

springboot hikari連接配接不釋放_芋道 Spring Boot 資料庫連接配接池入門1. 概述2. HikariCP 單資料源3. HikariCP 多資料源4. Druid 單資料源5. Druid 多資料源666. 彩蛋

繼續閱讀