點選上方“芋道源碼”,選擇“設為星标”
做積極的人,而不是積極廢人!
源碼精品專欄
- 原創 | 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
- 在
配置項下,我們可以添加 HikariCP 連接配接池的自定義配置。然後spring.datasource.hikari
會自動化配置 HikariCP 連接配接池。DataSourceConfiguration.Hikari
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 的執行個體,供池使用以記錄各種名額 | null | null | - |
healthCheckRegistry | 該屬性允許您指定池使用的Codahale / Dropwizard HealthCheckRegistry的執行個體來報告目前健康資訊 | null | null | - |
poolName | 連接配接池的使用者定義名稱,主要出現在日志記錄和JMX管理控制台中以識别池和池配置 | null | HikariPool-1 | - |
initializationFailTimeout | 如果池無法成功初始化連接配接,則此屬性控制池是否将 | 1 | 1 | - |
isolateInternalQueries | 是否在其自己的事務中隔離内部池查詢,例如連接配接活動測試 | false | false | - |
allowPoolSuspension | 控制池是否可以通過JMX暫停和恢複 | false | false | - |
readOnly | 從池中擷取的連接配接是否預設處于隻讀模式 | false | false | - |
registerMbeans | 是否注冊JMX管理Bean( ) | false | false | - |
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
兩個資料源的配置。而每個資料源的配置,和我們在 「2.2 應用配置檔案」 是一緻的。users
3.3 資料源配置類
3.3.1 錯誤的示例
在網上,我們會看到這樣配置多個資料源的配置類。代碼如下:
- 實際上,這樣做的話,在部分場景下,會存在問題,這是為什麼呢?
- 我們先來了解這段程式的用途。以
方法為例子:#ordersDataSource()
-
代碼段,會建立一個 DataSource 資料源。DataSourceBuilder.create().build()
- 搭配上
注解,會建立一個名字為@Bean(name = "ordersDataSource")
的 DataSource Bean 。這裡,我們使用 HikariCP ,是以傳回的是 HikariDataSource Bean 。"ordersDataSource"
-
注解,會将@ConfigurationProperties(prefix = "spring.datasource.orders")
配置項,逐個屬性指派給 DataSource Bean 。"spring.datasource.orders"
-
- 看起來貌似沒問題,但是如果每個資料源如果有 HikariCP 的
自定義配置項時,它的自定義配置項無法設定到 HikariDataSource Bean 中。因為,"hikari"
是"spring.datasource.orders.hikari"
的第二層屬性。而 HikariDataSource 的配置屬性在第一層,這就導緻無法正确的設定。"spring.datasource.orders"
雖然存在該問題,但是大多數項目,我們并不會自定義 HikariCP 的
"hikari"
配置項,是以這個問題就偷偷藏起來,**“不存在”**了。
3.3.2 正确的示例
當然,作為入門的示例,艿艿還是希望提供正确的做法。
在
cn.iocoder.springboot.lab19.datasourcepool.config
包路徑下,我們會建立 DataSourceConfig 配置類。代碼如下:
- 這塊代碼,我們是參考 Spring Boot
配置類來實作的。DataSourceConfiguration.Hikari
-
方法,建立#ordersDataSourceProperties()
資料源的 DataSourceProperties 配置對象。"orders"
-
注解,保證項目中有一個主的 DataSourceProperties Bean 。@Primary
-
代碼段,會建立一個 DataSourceProperties 資料源的配置對象。new DataSourceProperties()
- 搭配上
注解,會建立一個名字為@Bean(name = "ordersDataSourceProperties")
的 DataSourceProperties Bean 。"ordersDataSourceProperties"
-
注解,會将@ConfigurationProperties(prefix = "spring.datasource.orders")
配置項,逐個屬性指派給 DataSourceProperties Bean 。"spring.datasource.orders"
-
-
方法,建立#ordersDataSource()
資料源。orders
-
處,調用<1.1>
方法,獲得#ordersDataSourceProperties()
資料源的 DataSourceProperties 。orders
-
處,調用<1.2>
方法,建立 HikariDataSource 對象。這樣,#createHikariDataSource(DataSourceProperties properties)
配置項,逐個屬性指派給 HikariDataSource Bean 。"spring.datasource.orders"
- 搭配上
注解,會建立一個名字為@Bean(name = "ordersDataSource")
的 HikariDataSource Bean 。"ordersDataSource"
-
注解,會将 HikariCP 的@ConfigurationProperties(prefix = "spring.datasource.orders.hikari")
自定義配置項,逐個屬性指派給 HikariDataSource Bean 。"spring.datasource.orders.hikari"
-
-
資料源的配置,同上,就不重複解釋了。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 資料源的通用配置。其中,spring.datasource
配置項,需要主動設定使用 DruidDataSource 。因為預設情況下,spring.datasource.type
的 DataSourceBuilder 會按照spring-boot-starter-jdbc
的順序,嘗試推斷資料源的類型。DATA_SOURCE_TYPE_NAMES
-
配置項,設定 Druid 連接配接池的自定義配置。然後 DruidDataSourceAutoConfigure 會自動化配置 Druid 連接配接池。spring.datasource.druid
- 在 《Druid —— 配置屬性》 和 《DruidDataSource 配置屬性清單》 下,提供了各種 Druid 的配置項,胖友可以自己看看。
-
配置項,我們配置了 Druid StatFilter ,用于統計監控資訊。對應文檔 《Druid —— 配置_StatFilter》 。要注意,StatFilter 并不是我們說的filter.stat
,而是 Druid 提供的 Filter 拓展機制。javax.servlet.Filter
-
配置項,我們配置了 Druid StatViewServlet ,用于提供監控資訊的展示的 html 頁面和 JSON API 。對應文檔 《Druid —— 配置_StatViewServlet 配置》 。StatViewServlet 就是我們說的filter.stat-view-servlet
。javax.servlet.Filter
4.3 Application
建立
Application.java
類,配置
@SpringBootApplication
注解即可。代碼如下:
執行日志如下:
- 可以看到,DruidDataSource 成功初始化。
4.4 監控功能
因為我們在 「4.2 應用配置中」 中,做了如下操作:
- 通過
配置了 StatFilter ,統計監控資訊。spring.datasource.filter.stat
- 通過
配置了 StatViewServlet ,提供監控資訊的展示的 html 頁面和 JSON API 。spring.datasource.filter.stat-view-servlet
是以我們在啟動項目後,通路
http://127.0.0.1:8080/druid
位址,可以看到監控 html 頁面。如下圖所示:
- 在界面的頂部,提供了資料源、SQL 監控、SQL 防火牆等等功能。
- 每個界面上,可以通過 View JSON API 獲得資料的來源。同時,我們可以在 JSON API(
) 菜單對應的界面中,看到 StatViewServlet 内置的監控資訊的 JSON API 清單。http://127.0.0.1:8080/druid/api.html
- 因為監控資訊是存儲在 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
的方式,就能完成 DruidDataSource 的配置屬性設定。@ConfigurationProperties(prefix = "spring.datasource.orders")
- 在
配置項下,我們還是配置了spring.datasource.druid
和filter.stat
配置項,用于 Druid 監控功能。stat-view-servlet
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 2.X 入門》系列,已經 20 餘篇,覆寫了 MyBatis、Redis、MongoDB、ES、分庫分表、讀寫分離、SpringMVC、Webflux、權限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能測試等等内容。
提供近 3W 行代碼的 SpringBoot 示例,以及超 4W 行代碼的電商微服務項目。
擷取方式:點“在看”,關注公衆号并回複 666 領取,更多内容陸續奉上。