傳統模式:每次請求「建立連接 → 操作 → 關閉連接」,建立連接涉及 TCP 三次握手、SSL 握手、認證、分配會話資源,**極其耗時**(毫秒級)。高併發下頻繁創建/銷毀導致 CPU 飆升、內存抖動、數據庫連接數耗盡。
連接池方案:啟動時預創建連接池,請求時「借用 → 歸還」,實現連接復用,消除創建開銷。
initialSize),放入空閒隊列。maxActive → 創建新連接返回。maxActive → 阻塞等待 maxWait 毫秒 → 超時拋異常。maxIdle → 銷毀多餘連接;空閒數 < minIdle → 後台線程補充。<dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <!-- 間接依賴 commons-pool, commons-collections -->
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/csdn?useUnicode=true&characterEncoding=UTF-8 jdbc.user=root jdbc.password=123456 # 連接池參數 initialSize=5 maxActive=20 maxIdle=10 minIdle=5 maxWait=60000
package com.daliu.jdbc;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import org.apache.commons.dbcp.BasicDataSource;
public class DBUtil {
private static BasicDataSource dataSource;
private static ThreadLocal threadLocal = new ThreadLocal<>();
static {
try {
Properties prop = new Properties();
InputStream is = DBUtil.class.getClassLoader()
.getResourceAsStream("com/daliu/jdbc/db.properties");
prop.load(is);
is.close();
dataSource = new BasicDataSource();
dataSource.setDriverClassName(prop.getProperty("jdbc.driver"));
dataSource.setUrl(prop.getProperty("jdbc.url"));
dataSource.setUsername(prop.getProperty("jdbc.user"));
dataSource.setPassword(prop.getProperty("jdbc.password"));
dataSource.setInitialSize(Integer.parseInt(prop.getProperty("initialSize")));
dataSource.setMaxActive(Integer.parseInt(prop.getProperty("maxActive")));
dataSource.setMaxIdle(Integer.parseInt(prop.getProperty("maxIdle")));
dataSource.setMinIdle(Integer.parseInt(prop.getProperty("minIdle")));
dataSource.setMaxWait(Long.parseLong(prop.getProperty("maxWait")));
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
public static Connection getConnection() throws SQLException {
Connection conn = dataSource.getConnection();
threadLocal.set(conn); // 綁定當前線程,便於事務管理
return conn;
}
public static void closeConnection() {
Connection conn = threadLocal.get();
if (conn != null) {
try { conn.close(); } catch (SQLException e) { e.printStackTrace(); }
threadLocal.remove();
}
}
public static void main(String[] args) throws SQLException {
System.out.println(getConnection());
}
}
| 參數 | 含義 | 建議值 | 調優思路 |
|---|---|---|---|
initialSize | 啟動建立連接數 | 5~10 | 避免啟動慢,預熱池 |
maxActive | 最大活躍連接數 | 20~100 | 根據 CPU 核心數、業務併發、DB max_connections 綜合評估 |
maxIdle | 最大空閒連接數 | 接近 maxActive | 過小導致頻繁銷毀/創建抖動;過大佔用 DB 連接槽 |
minIdle | 最小空閒連接數 | 5~10 | 保持基線,避免冷啟動延遲 |
maxWait | 獲取連接最大等待時間(ms) | 5000~30000 | 防止請求無限掛起,超時快速失敗 |
validationQuery | 驗證連接有效性 SQL | SELECT 1 | 配合 testOnBorrow/testWhileIdle 防止斷連 |
validationQuery + testOnBorrow=true 或 testWhileIdle=true + timeBetweenEvictionRunsMillis,防止防火牆/DB 斷開空閒連接導致借用失效。NumActive, NumIdle, WaitThreadCount,設置告警閾值。Connection.close() 後繼續使用該對象。ThreadLocal 或 Spring TransactionSynchronizationManager 綁定。