經常使用Java數據庫鏈接池

概述

在這裏所謂的數據庫鏈接是指經過網絡協議與數據庫服務之間創建的TCP鏈接。一般,與數據庫服務進行通訊的網絡協議無需由應用程序自己實現,緣由有三:html

  1. 實現複雜度大,須要充分理解和掌握相應的通訊協議。
  2. 代碼難以複用,每一個應用程序都須要獨立實現一套對應的網絡協議(不一樣公司之間,同一公司的不一樣技術棧之間難以複用實現相同協議的代碼)
  3. 性能難以保證,不一樣的網絡協議實現可能存在巨大的性能差距。

正由於如此,因此現實的實現方式是:
首先,定義網絡協議標準,這樣只要支持這個標準協議的數據庫就可使用相應的客戶端與之通訊。
其次,將實現這個標準協議的客戶端獨立爲一個通訊庫,這樣只須要在應用程序中使用這個通訊組件庫就能夠方便地實現與數據庫進行交互。java

一般,咱們將實現了網絡協議的通訊庫稱之爲數據庫驅動程序。固然,對於不一樣的編程語言,須要對應編寫相應的數據庫驅動實現。以與關係型數據庫通訊爲例,在Java中實現的驅動程序爲JDBC,Python中的驅動程序爲MySQLdb。
因爲經過TCP與數據庫創建網絡鏈接的代價很是高昂,並且耗時(TCP創建鏈接須要「三次握手」,斷開鏈接須要「四次握手」)。因此在實踐中一般不直接單獨使用鏈接進行數據庫操做,而是使用鏈接池的方式,這主要是處於如下兩方面的考慮:mysql

  1. 應用程序自己須要更低的響應時間,若是每次數據庫操做都須要通過「創建鏈接->通訊(增刪改查)->斷開鏈接」這個過程,那麼勢必會致使響應延時的增長。
  2. 避免服務器資源被耗盡,隨着業務量的增大,對應的數據庫操做必然會隨之增長,若是對客戶端的鏈接數不加以控制,可能會致使數據庫服務器的CPU和內存資源被大量的網絡鏈接快速耗盡,這樣將致使服務不可用。

在Java中使用得比較流行的數據庫鏈接池主要有:DBCP,c3p0,druid。
另外,不論使用什麼鏈接池,低層都是使用JDBC鏈接,即:在應用程序中都須要加載JDBC驅動程序。git

DBCP

https://commons.apache.org/proper/commons-dbcp/index.html
DBCP是Apache下獨立的數據庫鏈接池組件,在Tomcat中使用的鏈接池組件就是DBCP,支持JDBC3,JDBC4。關於更多JDBC版本信息,詳見:https://en.wikipedia.org/wiki/Java_Database_Connectivitygithub

c3p0

http://www.mchange.com/projects/c3p0/
使用c3p0有多種方式,如:既能夠直接使用API方式配置c3p0,也能夠經過文件的方式進行配置,配置文件有2種形式:properties或xml文件。sql

<dependencies>
    <!-- JDBC驅動 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.42</version>
    </dependency>
    
    <!-- c3p0鏈接池 -->
    <dependency>
        <groupId>com.mchange</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.5.2</version>
    </dependency>

    <!-- 日誌組件 -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.25</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-core</artifactId>
        <version>1.2.3</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.3</version>
    </dependency>
</dependencies>

1.使用Java API方式配置c3p0數據庫

ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass( "com.mysql.jdbc.Driver" ); //loads the jdbc driver            
cpds.setJdbcUrl("jdbc:mysql://host:port/db");
cpds.setUser("username");                                  
cpds.setPassword("password");                                  
    
cpds.setMinPoolSize(5);                                     
cpds.setMaxPoolSize(20);
cpds.setAcquireIncrement(5);

// 直接從鏈接池中獲取鏈接
Connection conn = cpds.getConnection();
query(conn);

// 關閉鏈接池
// cpds.close();

2.使用文件方式配置c3p0
2.1 使用c3p0.properties文件進行配置
須要在classpath路徑下添加配置文件:c3p0.properties,內容以下:apache

c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql://host:port/db
c3p0.user=root
c3p0.password=
c3p0.minPoolSize=5
c3p0.maxPoolSize=20
c3p0.acquireIncrement=5

在應用程序中只須要直接建立ComboPooledDataSource對象便可(c3p0會自動從classpath加載c3p0.properties中的配置信息):編程

ComboPooledDataSource cpds = new ComboPooledDataSource();
Connection conn = cpds.getConnection();
query(conn);
cpds.close();

注意: 使用c3p0.properties做爲配置文件時,每一個參數的name前綴必須是「c3p0」,如:「c3p0.driverClass=com.mysql.jdbc.Driver」。api

2.2 使用c3p0-config.xml文件進行配置
使用這種方式會比使用c3p0.properties更加高級,支持配置多個數據源,一樣須要在classpath路徑下添加文件:c3p0-config.xml。

<c3p0-config>
    <!-- 默認數據源 -->
    <default-config>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://host:port/db</property>
        <property name="user">username</property>
        <property name="password">password</property>
        <property name="minPoolSize">5</property>
        <property name="maxPoolSize">20</property>
        <property name="acquireIncrement">5</property>
    </default-config>

    <!-- 定義帶名稱的數據源 -->
    <named-config name="myDataSource">
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/test_jdbc</property>
        <property name="user">root</property>
        <property name="password"></property>
        <property name="minPoolSize">5</property>
        <property name="maxPoolSize">20</property>
        <property name="acquireIncrement">5</property>
    </named-config>
</c3p0-config>
// 使用默認數據源
// ComboPooledDataSource cpds = new ComboPooledDataSource();

// 使用指定名稱的數據源
ComboPooledDataSource cpds = new ComboPooledDataSource("myDataSource");
Connection conn = cpds.getConnection();
query(conn);
cpds.close();

3.c3p0經常使用配置

<c3p0-config>
    <default-config>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://host:port/db</property>
        <property name="user">username</property>
        <property name="password">password</property>

        <!-- 鏈接池初始化時建立的鏈接數,默認值: 3 -->
        <property name="initialPoolSize">3</property>
        <!-- 鏈接池保持的最小鏈接數,默認值: 3 -->
        <property name="minPoolSize">3</property>
        <!-- 鏈接池中擁有的最大鏈接數,若是得到新鏈接時會使鏈接總數超過這個值則不會再獲取新鏈接,而是等待其餘鏈接釋放。 -->
        <property name="maxPoolSize">15</property>
        <!-- 鏈接池在無空閒鏈接可用時一次性建立的新數據庫鏈接數,默認值: 3 -->
        <property name="acquireIncrement">3</property>
        <!-- 鏈接的最大空閒時間,若是超過這個時間,某個數據庫鏈接尚未被使用,則會斷開掉這個鏈接。爲0,則永遠不會斷開鏈接。默認值: 0,單位: 秒 -->
        <property name="maxIdleTime">0</property>
        <!-- 鏈接測試語句 -->
        <property name="preferredTestQuery">select 1</property>
        <!-- 用來配置測試空閒鏈接的間隔時間。能夠用來解決MySQL 8小時斷開鏈接的問題。由於它保證鏈接池會每隔必定時間對空閒鏈接進行一次測試,從而保證有效的空閒鏈接能每隔必定時間訪問一次數據庫,將MySQL8小時無會話的狀態打破。爲0則不測試。默認值:0,單位: 秒 -->
        <property name="idleConnectionTestPeriod">30</property>
        <!-- 鏈接池在得到新鏈接失敗時重試的次數,若是小於等於0則無限重試直至鏈接得到成功。默認值: 30 -->
        <property name="acquireRetryAttempts">30</property>
        <!-- 鏈接池在得到新鏈接時的間隔時間,默認值: 1000,單位: 毫秒 -->
        <property name="acquireRetryDelay">1000</property>
    </default-config>
</c3p0-config>

druid

https://github.com/alibaba/druid
阿里開源的druid不單純是一個鏈接池,還添加了監控功能,目前已是很是受推崇的鏈接池組件,詳細配置參數請參考官網。

固然,還存在一些其餘的數據庫鏈接池實現,例如:Tomcat本身就實現了一個鏈接池組件,根據官方的說法,這個鏈接池正是爲了在Tomcat中替換DBCP,詳見:https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html

【參考】
http://josh-persistence.iteye.com/blog/2229929 深刻淺出數據庫鏈接池c3p0

相關文章
相關標籤/搜索