首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 手寫數據庫連接池:從原理到完整實現

     編輯:Java 相關知識

池化技術核心思想

對象池適用於「創建開銷大、頻繁使用、數量可控」的資源。數據庫連接典型符合:TCP 三次握手 + SSL 握手 + 認證 + 會話初始化,單次耗時 10-100ms;數據庫最大連接數受限(如 MySQL 默認 151)。連接池預創建連接,借用/歸還替代創建/關閉,大幅降低延遲、控制併發。

架構設計三大核心組件

1. ConnectionParam - 參數建構器

採用 Builder 模式,區分必選/可選參數,支持鏈式調用:

public class ConnectionParam {
    private final String driver, url, user, password;
    private final int minConnection, maxConnection, minIdle;
    private final long maxWait;

    public static class ConnectionParamBuilder implements Builder<ConnectionParam> {
        // 必選參數
        private final String driver, url, user, password;
        // 可選參數默認值
        private int minConnection = 5, maxConnection = 50, minIdle = 5;
        private long maxWait = 30000;

        public ConnectionParamBuilder(String driver, String url, String user, String password) {...}
        public ConnectionParamBuilder maxConnection(int v) { this.maxConnection = v; return this; }
        // 其他 setter 省略
        public ConnectionParam build() { return new ConnectionParam(this); }
    }
}

2. ConnectionPool - 連接池核心邏輯

實現 DataSource 接口,雙容器設計:

  • ArrayBlockingQueue<Connection> idleQueue:有界阻塞隊列,存放空閒連接,支持超時獲取。
  • Vector<Connection> busyVector:同步列表,追蹤活躍連接。

關鍵創新:動態代理攔截 close()

@Override
public Connection getConnection() throws SQLException {
    Connection rawConn = idleQueue.poll(maxWait, TimeUnit.MILLISECONDS);
    if (rawConn == null) { ensureCapacity(); return null; }
    busyVector.add(rawConn);
    return (Connection) Proxy.newProxyInstance(
        getClass().getClassLoader(),
        new Class[]{Connection.class},
        (proxy, method, args) -> {
            if (!"close".equals(method.getName()))
                return method.invoke(rawConn, args);
            // 歸還而非關閉
            idleQueue.offer(rawConn);
            busyVector.remove(rawConn);
            return null;
        }
    );
}

擴容策略:ensureCapacity() 按 minIdle 批量補充,不超 maxConnection。

3. ConnectionPoolFactory - 多池管理中心

線程安全的 ConcurrentHashMap<String, ConnectionPool> 管理多個命名池:

public static Connection getConnection(String poolName) throws SQLException {
    ConnectionPool pool = poolMap.get(poolName);
    if (pool == null) throw new IllegalArgumentException("Pool not found: " + poolName);
    return pool.getConnection();
}
public static void registerConnectionPool(String name, ConnectionParam param) {
    if (poolMap.containsKey(name)) throw new IllegalArgumentException("Pool exists: " + name);
    poolMap.put(name, new ConnectionPool(param));
}
public static void unRegisterConnectionPool(String name) {
    ConnectionPool pool = poolMap.remove(name);
    if (pool != null) new Thread(pool::clear).start(); // 異步銷毀
}

完整類清單與依賴關係

database.config.ParamConfiguration     // 常量默認值
database.Builder                       // 構建器接口
database.ConnectionParam               // 參數實體 + Builder
database.factory.ConnectionPool        // 連接池實現 (DataSource)
database.factory.ConnectionPoolFactory // 工廠管理類
database.factory.ConnectionPoolFactoryTest // JUnit 測試

JUnit 測試驗證邏輯

@Test
public void testGetConnection() throws SQLException {
    // 註冊池
    ConnectionParam param = new ConnectionParam.ConnectionParamBuilder(
        "com.mysql.jdbc.Driver", "jdbc:mysql://localhost:3306/test", "root", "root"
    ).build();
    ConnectionPoolFactory.registerConnectionPool("test", param);

    // 併發獲取 12 個連接
    List<Connection> conns = new ArrayList<>();
    for (int i = 0; i < 12; i++) conns.add(ConnectionPoolFactory.getConnection("test"));
    printStats(); // idle=5, busy=12, size=17 (初始5+擴容7+minIdle5=17)

    // 歸還
    for (Connection c : conns) if (c != null) c.close();
    printStats(); // idle=17, busy=0, size=17

    // 二次獲取驗證復用
    conns.clear();
    for (int i = 0; i < 12; i++) conns.add(ConnectionPoolFactory.getConnection("test"));
    printStats(); // idle=5, busy=12, size=17

    ConnectionPoolFactory.unRegisterConnectionPool("test");
}

生產級差距分析

維度教學版生產級 (HikariCP/Druid)
連接驗證無空閒檢測、存活測試、驗證查詢
洩漏檢測無堆棧追蹤定位未歸還連接
PreparedStatement 緩存無每連接 LRU 緩存
指標監控無JMX/Prometheus/內建監控頁
動態配置無運行時調整池大小
高可用無熔斷、降級、多數據源負載均衡

結語

手寫連接池是理解「資源池化、動態代理、併發容器、JDBC 規範」的最佳途徑。生產環境請直接使用 HikariCP(Spring Boot 2.x 默認)或 Druid(阿里巴巴出品,監控強),兩者經過億級流量驗證,性能與穩健性遠超教學實現。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved