連接池是數據庫訪問性能的核心基礎設施。Spring Boot 2.x/3.x 默認採用 HikariCP,Druid 為國產強項。本文深度解析兩大連接池關鍵參數、監控體系、動態配置與多數據源隔離實戰。
// DataSourceAutoConfiguration 簡化邏輯
@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class})
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(name = "spring.datasource.type")
public DataSource dataSource(DataSourceProperties props) {
return props.initializeDataSourceBuilder().build();
}
// HikariCP 優先 (類路徑存在)
@Bean
@ConditionalOnClass(HikariDataSource.class)
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.hikari.*", matchIfMissing = true)
public HikariDataSource hikariDataSource(DataSourceProperties props) { ... }
// Druid 次之
@Bean
@ConditionalOnClass(DruidDataSource.class)
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.druid.*", matchIfMissing = false)
public DruidDataSource druidDataSource(DataSourceProperties props) { ... }
}
| 參數 | 默認值 | 建議生產值 | 說明 |
|---|---|---|---|
| maximumPoolSize | 10 | CPU核心數 * 2 + 有效磁盤數 (OLTP: 20-50) | 最大連接數,過大導致數據庫壓力、上下文切換 |
| minimumIdle | 同 maximumPoolSize | 同 maximumPoolSize (固定池) 或 10-20 | 最小空閒連接,固定池避免伸縮開銷 |
| connectionTimeout | 30000ms | 20000-30000ms | 獲取連接超時,過短易誤報錯 |
| idleTimeout | 600000ms | 300000-600000ms | 空閒連接回收時間,需 < maxLifetime |
| maxLifetime | 1800000ms | 1200000-1800000ms (30分鐘) | 連接最大壽命,必須 < 數據庫 wait_timeout |
| connectionTestQuery | 無 (JDBC4 自動) | SELECT 1 (MySQL) / SELECT 1 FROM DUAL (Oracle) | 連接驗證查詢,驅動不支援 isValid() 時必填 |
| validationTimeout | 5000ms | 5000ms | 驗證查詢超時 |
| leakDetectionThreshold | 0 (關閉) | 30000-60000ms | 連接洩露檢測閾值,0 關閉,生產建議開啟 |
| autoCommit | true | false (由事務管理器控制) | 自動提交,Spring 事務建議關閉 |
| poolName | HikariPool-N | 業務標識 (如 order-hikari) | 監控/日誌識別 |
| registerMbeans | false | true | 暴露 JMX MBean,Prometheus/Grafana 採集 |
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/app?useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true
username: root
password: root
hikari:
maximum-pool-size: 30
minimum-idle: 10
connection-timeout: 20000
idle-timeout: 300000
max-lifetime: 1200000
connection-test-query: SELECT 1
validation-timeout: 5000
leak-detection-threshold: 30000
auto-commit: false
pool-name: AppHikariPool
register-mbeans: true
# 傳遞驅動屬性 (需字符串)
data-source-properties:
cachePrepStmts: "true"
prepStmtCacheSize: "250"
prepStmtCacheSqlLimit: "2048"
useServerPrepStmts: "true"
rewriteBatchedStatements: "true"
maintainTimeStats: "false"
| 參數 | 默認值 | 建議生產值 | 說明 |
|---|---|---|---|
| initialSize | 0 | 5-10 | 初始化連接數,啟動預熱 |
| minIdle | 0 | 5-10 | 最小空閒 |
| maxActive | 8 | 20-50 | 最大活躍連接 |
| maxWait | 60000 | 30000-60000 | 獲取連接最大等待 |
| validationQuery | 無 | SELECT 1 | 驗證查詢 |
| testWhileIdle | false | true | 空閒時驗證 (配合 timeBetweenEvictionRunsMillis) |
| testOnBorrow | false | false | 借用時驗證 (影響性能,建議關閉) |
| testOnReturn | false | false | 歸還時驗證 |
| timeBetweenEvictionRunsMillis | -1 (不檢測) | 60000-300000 | 空閒連接檢測間隔 |
| minEvictableIdleTimeMillis | 300000 | 300000-600000 | 連接最小生存時間 |
| filters | 無 | stat,wall,slf4j | stat-監控、wall-防火牆、slf4j-日誌 |
| poolPreparedStatements | false | true | PSCache 開啟 (Oracle/PostgreSQL 效果明顯) |
| maxPoolPreparedStatementPerConnectionSize | 20 | 20-100 | 每連接 PSCache 大小 |
| connectionProperties | 無 | druid.stat.mergeSql=true;druid.stat.slowSqlMillis=3000 | 合併 SQL 統計、慢 SQL 閾值 |
spring:
datasource:
druid:
# ... 上述核心參數
web-stat-filter:
enabled: true
url-pattern: /*
exclusions: "*.js,*.css,*.png,*.jpg,*.gif,*.ico,/druid/*"
profile-enable: true # URL 調用統計
stat-view-servlet:
enabled: true
url-pattern: /druid/*
login-username: admin
login-password: ${DRUID_PASSWORD:admin123} # 環境變量注入
reset-enable: false
allow: 127.0.0.1,10.0.0.0/8 # 白名單
deny: 192.168.1.100
spring:
datasource:
# 主庫 (寫)
master:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://master-db:3306/app?useSSL=false&serverTimezone=UTC
username: root
password: ${MASTER_PWD}
hikari:
maximum-pool-size: 20
pool-name: MasterHikariPool
# 從庫 (讀)
slave:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://slave-db:3306/app?useSSL=false&serverTimezone=UTC
username: readonly
password: ${SLAVE_PWD}
hikari:
maximum-pool-size: 30
pool-name: SlaveHikariPool
AOP 讀寫分離 (抽象路由)
動態數據源持有者
(); public static void setDataSourceType(String type) { CONTEXT.set(type); } public static String getDataSourceType() { return CONTEXT.get(); } public static void clear() { CONTEXT.remove(); } } @Primary @Bean public DataSource routingDataSource(@Qualifier("masterDataSource") DataSource master, @Qualifier("slaveDataSource") DataSource slave) { AbstractRoutingDataSource proxy = new AbstractRoutingDataSource() { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSourceType(); } }; Map<Object, Object> map = new HashMap<>(); map.put("master", master); map.put("slave", slave); proxy.setTargetDataSources(map); proxy.setDefaultTargetDataSource(master); proxy.afterPropertiesSet(); return proxy; } 連接池監控與告警體系
1. JMX + Prometheus (HikariCP)
# application.yml spring: datasource: hikari: register-mbeans: true # 依賴 &# 暴露端點 management: endpoints: web: exposure: include: prometheus,metrics,health endpoint: prometheus: enabled: true io.micrometer micrometer-registry-prometheus 關鍵指標
hikaricp_connections_active / _idle / _pending / _max / _minhikaricp_connections_creation_seconds / _usage_secondshikaricp_connections_timeout_total (獲取超時計數)/druid/index.html 查看 SQL 統計、慢 SQL、連接池狀態、URI 監控druid-spring-boot-starter 自動暴露 /actuator/prometheus 指標minimumIdle = maximumPoolSize 避免伸縮抖動poolPreparedStatements=true (Druid) / cachePrepStmts=true (HikariCP+MySQL)rewriteBatchedStatements=true 將 batch 合併為多值 INSERTleakDetectionThreshold=30000 開發/測試環境必開slowSqlMillis=3000 結合 EXPLAIN 分析testWhileIdle=true + validationQuery=SELECT 1連接池不是「配好即忘」的基礎設施。HikariCP 以極致性能、輕量級贏得 Spring Boot 默認地位;Druid 以豐富監控、SQL 防火牆、國產化優勢佔據國內大廠主流。核心調優邏輯:池大小匹配業務併發 → 生命周期短於數據庫超時 → 空閒驗證防殭屍 → PSCache/批量重寫提升吞吐 → 全鏈路監控告警。多數據源場景下,AbstractRoutingDataSource + AOP 路由實現讀寫分離/業務隔離,保持代碼整潔。建議將連接池參數外部化至配置中心,支援運行期動態調整,應對突發流量。