1. 程式人生 > >Spring下配置幾種常用連線池

Spring下配置幾種常用連線池

1、連線池概述
  資料庫連線是一種關鍵的有限的昂貴的資源,這一點在多使用者的網頁應用程式中體現得尤為突出。對資料庫連線的管理能顯著影響到整個
應用程式的伸縮性和健壯性,影響到程式的效能指標。資料庫連線池正是針對這個問題提出來的。
  資料庫連線池負責分配、管理和釋放資料庫連線,它允許應用程式重複使用一個現有的資料庫連線,而再不是重新建立一個;釋放空閒時
間超過最大空閒時間的資料庫連線來避免因為沒有釋放資料庫連線而引起的資料庫連線遺漏。這項技術能明顯提高對資料庫操作的效能。
  資料庫連線池在初始化時將建立一定數量的資料庫連線放到連線池中,這些資料庫連線的數量是由最小資料庫連線數來設定的。無論這些
資料庫連線是否被使用,連線池都將一直保證至少擁有這麼多的連線數量。連線池的最大資料庫連線數量限定了這個連線池能佔有的最大連線
數,當應用程式向連線池請求的連線數超過最大連線數量時,這些請求將被加入到等待佇列中。資料庫連線池的最小連線數和最大連線數的設
置要考慮到下列幾個因素:
  1) 最小連線數是連線池一直保持的資料庫連線,所以如果應用程式對資料庫連線的使用量不大,將會有大量的資料庫連線資源被浪費;
  2) 最大連線數是連線池能申請的最大連線數,如果資料庫連線請求超過此數,後面的資料庫連線請求將被加入到等待佇列中,這會影響之
後的資料庫操作。
  3) 如果最小連線數與最大連線數相差太大,那麼最先的連線請求將會獲利,之後超過最小連線數量的連線請求等價於建立一個新的資料庫
連線。不過,這些大於最小連線數的資料庫連線在使用完不會馬上被釋放,它將被放到連線池中等待重複使用或是空閒超時後被釋放。
  目前常用的連線池有:C3P0、DBCP、Proxool

  • C3P0比較耗費資源,效率方面可能要低一點。
  • DBCP在實踐中存在BUG,在某些種情會產生很多空連線不能釋放,Hibernate3.0已經放棄了對其的支援。
  • Proxool的負面評價較少,現在比較推薦它,而且它還提供即時監控連線池狀態的功能,便於發現連線洩漏的情況。

  不管通過何種持久化技術,都必須通過資料連線訪問資料庫,在Spring中,資料連線是通過資料來源獲得的。在以往的應用中,資料來源一般是

Web應用伺服器提供的。在Spring中,你不但可以通過JNDI獲取應用伺服器的資料來源,也可以直接在Spring容器中配置資料來源,此外,

你還可以通過程式碼的方式建立一個數據源,以便進行無依賴的單元測試。

2、DBCP資料來源

  DBCP類包為commons-dbcp.jar,DBCP是一個依賴 Jakarta commons-pool物件池機制的資料庫連線池,所以還應包含commons-pool.jar。

bean配置片段:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"        
        destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />       
    <property name="url" value="jdbc:mysql://localhost:3306/sampledb" />       
    <property name="username" value="root" />       
    <property name="password" value="1234" />       
</bean>
常用屬性:
BasicDataSource提供了close()方法關閉資料來源,所以必須設定destroy-method=”close”屬性, 以便Spring容器關閉時,資料來源能夠正常關閉。
    defaultAutoCommit:設定從資料來源中返回的連線是否採用自動提交機制,預設值為 true; 
    defaultReadOnly:設定資料來源是否僅能執行只讀操作, 預設值為 false; 
    maxActive:最大連線資料庫連線數,設定為0時,表示沒有限制; 
    maxIdle:最大等待連線中的數量,設定為0時,表示沒有限制; 
    maxWait:最大等待秒數,單位為毫秒, 超過時間會報出錯誤資訊; 
    validationQuery:用於驗證連線是否成功的查詢SQL語句,SQL語句必須至少要返回一行資料, 如你可以簡單地設定為:“select count(*) from user”; 
    removeAbandoned:是否自我中斷,預設是 false ; 
    removeAbandonedTimeout:幾秒後資料連線會自動斷開,在removeAbandoned為true,提供該值; 
    logAbandoned:是否記錄中斷事件, 預設為 false;

3、C3P0資料來源 
    C3P0是一個開放原始碼的JDBC資料來源實現專案,它在lib目錄中與Hibernate一起釋出,實現了JDBC3和JDBC2擴充套件規範說明的 Connection 和Statement 池。C3P0類包為c3p0-0.9.0.4.jar。

bean配置片段:

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"        
        destroy-method="close">       
    <property name="driverClass" value="com.mysql.jdbc.Driver"/>       
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/sampledb"/>       
    <property name="user" value="root"/>       
    <property name="password" value="1234"/>       
</bean>

常用屬性:
ComboPooledDataSource和BasicDataSource一樣提供了一個用於關閉資料來源的close()方法,這樣我們就可以保證Spring容器關閉時資料來源能夠成功釋放。 
  C3P0擁有比DBCP更豐富的配置屬性,通過這些屬性,可以對資料來源進行各種有效的控制: 
  acquireIncrement:當連線池中的連線用完時,C3P0一次性建立新連線的數目; 
    acquireRetryAttempts:定義在從資料庫獲取新連線失敗後重復嘗試獲取的次數,預設為30; 
    acquireRetryDelay:兩次連線中間隔時間,單位毫秒,預設為1000; 
    autoCommitOnClose:連線關閉時預設將所有未提交的操作回滾。預設為false; 
    automaticTestTable: C3P0將建一張名為Test的空表,並使用其自帶的查詢語句進行測試。如果定義了這個引數,那麼屬性preferredTestQuery將被忽略。
你不能在這張Test表上進行任何操作,它將中為C3P0測試所用,預設為null; 
    breakAfterAcquireFailure:獲取連線失敗將會引起所有等待獲取連線的執行緒丟擲異常。但是資料來源仍有效保留,並在下次呼叫getConnection()的時候繼續嘗試獲取連線。
如果設為true,那麼在嘗試獲取連線失敗後該資料來源將申明已斷開並永久關閉。預設為 false; 
    checkoutTimeout:當連線池用完時客戶端呼叫getConnection()後等待獲取新連線的時間,超時後將丟擲SQLException,如設為0則無限期等待。單位毫秒,預設為0; 
    connectionTesterClassName: 通過實現ConnectionTester或QueryConnectionTester的類來測試連線,類名需設定為全限定名。
預設為 com.mchange.v2.C3P0.impl.DefaultConnectionTester; 
    idleConnectionTestPeriod:隔多少秒檢查所有連線池中的空閒連線,預設為0表示不檢查; 
    initialPoolSize:初始化時建立的連線數,應在minPoolSize與maxPoolSize之間取值。預設為3; 
    maxIdleTime:最大空閒時間,超過空閒時間的連線將被丟棄。為0或負數則永不丟棄。預設為0; 
    maxPoolSize:連線池中保留的最大連線數。預設為15; 
    maxStatements:JDBC的標準引數,用以控制資料來源內載入的PreparedStatement數量。但由於預快取的Statement屬於單個Connection而不是整個連線池。
所以設定這個引數需要考慮到多方面的因素,如果maxStatements與 maxStatementsPerConnection均為0,則快取被關閉。預設為0; 
    maxStatementsPerConnection:連線池內單個連線所擁有的最大快取Statement數。預設為0; 
    numHelperThreads:C3P0是非同步操作的,緩慢的JDBC操作通過幫助程序完成。擴充套件這些操作可以有效的提升效能,通過多執行緒實現多個操作同時被執行。預設為3; 
    preferredTestQuery:定義所有連線測試都執行的測試語句。在使用連線測試的情況下這個引數能顯著提高測試速度。測試的表必須在初始資料來源的時候就存在。預設為null; 
    propertyCycle: 使用者修改系統配置引數執行前最多等待的秒數。預設為300; 
    testConnectionOnCheckout:因效能消耗大請只在需要的時候使用它。如果設為true那麼在每個connection提交的時候都將校驗其有效性。
建議使用idleConnectionTestPeriod或automaticTestTable 等方法來提升連線測試的效能。預設為false; 
    testConnectionOnCheckin:如果設為true那麼在取得連線的同時將校驗連線的有效性。預設為false。

4、Proxool資料來源

  sourceforge下的一個開源專案,這個專案提供一個健壯、易用的連線池,最為關鍵的是這個連線池提供監控的功能,方便易用,便於發現連線洩漏的情況。

<bean id="dataSource"
    class="org.logicalcobwebs.proxool.ProxoolDataSource">
    <property name="driver">
        <value>com.mysql.jdbc.Driver</value>
    </property>
    <property name="driverUrl">
        <value>jdbc:mysql://localhost:3306/sampledb?user=root&password=1234</value>
    </property>
    <property name="user" value="yourname" />
    <property name="password" value="yourpass" />
    <property name="alias" value="Pool_dbname" />
    <property name="houseKeepingSleepTime" value="90000" />
    <property name="prototypeCount" value="0" />
    <property name="maximumConnectionCount" value="50" />
    <property name="minimumConnectionCount" value="2" />
    <property name="simultaneousBuildThrottle" value="50" />
    <property name="maximumConnectionLifetime" value="14400000" />
    <property name="houseKeepingTestSql" value="select CURRENT_DATE" />
</bean>

這種方式需要把使用者名稱和密碼寫在連線串裡面,ProxoolDataSource類提供的user,password屬性似乎沒有什麼用。
無論提供什麼,它都會以空使用者名稱、密碼去連線資料庫,但是user,password兩個屬性必須設定,否則hibernate會報空指標錯誤。

常用配置:

fatal-sql-exception: 它是一個逗號分割的資訊片段.當一個SQL異常發生時,他的異常資訊將與這個資訊片段進行比較.如果在片段中存在,那麼這個異常將被認為是個致命錯誤 
(Fatal SQL Exception ).這種情況下,資料庫連線將要被放棄.無論發生什麼,這個異常將會被重擲以提供給消費者.使用者最好自己配置一個不同的異常來丟擲.
  fatal-sql-exception-wrapper-class:正如上面所說,你最好配置一個不同的異常來重擲.利用這個屬性,使用者可以包裝
  SQLException,使他變成另外一個異常.這個異常或者繼承SQLException或者繼承字RuntimeException.proxool
自帶了2個實現:'org.logicalcobwebs.proxool.FatalSQLException' 和'org.logicalcobwebs.proxool.FatalRuntimeException'.後者更合適.
  house-keeping-sleep-time: house keeper 保留執行緒處於睡眠狀態的最長時間,house keeper 的職責就是檢查各個連線的狀態,並判斷是否需要銷燬或者建立.
  house-keeping-test-sql: 如果發現了空閒的資料庫連線.house keeper 將會用這個語句來測試.這個語句最好非常快的被執行.如果沒有定義,測試過程將會被忽略。
  injectable-connection-interface: 允許proxool實現被代理的connection物件的方法.
  injectable-statement-interface: 允許proxool實現被代理的Statement 物件方法.
  injectable-prepared-statement-interface: 允許proxool實現被代理的PreparedStatement 物件方法.
  injectable-callable-statement-interface: 允許proxool實現被代理的CallableStatement 物件方法.
  jmx: 如果屬性為true,就會註冊一個訊息Bean到jms服務,訊息Bean物件名: "Proxool:type=Pool, name=<alias>". 預設值為false.
  jmx-agent-id: 一個逗號分隔的JMX代理列表(如使用MBeanServerFactory.findMBeanServer(String agentId)註冊的連線池。)這個屬性是僅當"jmx"屬性設定為"true"才有效。
所有註冊jmx伺服器使用這個屬性是不確定的
  jndi-name: 資料來源的名稱
  maximum-active-time: 如果housekeeper 檢測到某個執行緒的活動時間大於這個數值.它將會殺掉這個執行緒.
所以確認一下你的伺服器的頻寬.然後定一個合適的值.預設是5分鐘.
  maximum-connection-count: 最大的資料庫連線數.
  maximum-connection-lifetime: 一個執行緒的最大壽命.
  minimum-connection-count: 最小的資料庫連線數
  overload-without-refusal-lifetime: 這可以幫助我們確定連線池的狀態。如果我們已經拒絕了一個連線在這個設定值(毫秒),然後被認為是超載。預設為60秒。
  prototype-count: 連線池中可用的連線數量.如果當前的連線池中的連線少於這個數值.新的連線將被建立(假設沒有超過最大可用數).例如.我們有3個活動連線2個可用連線,
而我們的prototype-count是4,那麼資料庫連線池將試圖建立另外2個連線.這和 minimum-connection-count不同. minimum-connection-count
把活動的連線也計算在內.prototype-count 是spare connections 的數量.
  recently-started-threshold: 這可以幫助我們確定連線池的狀態,連線數少還是多或超載。只要至少有一個連線已開始在此值(毫秒)內,或者有一些多餘的可用連線,
那麼我們假設連線池是開啟的。預設為60秒
  simultaneous-build-throttle: 這是我們可一次建立的最大連線數。那就是新增的連線請求,但還沒有可供使用的連線。由於連線可以使用多執行緒,
在有限的時間之間建立聯絡從而帶來可用連線,但是我們需要通過一些方式確認一些執行緒並不是立即響應連線請求的,預設是10。
  statistics: 連線池使用狀況統計。引數“10s,1m,1d”
  statistics-log-level: 日誌統計跟蹤型別。引數“ERROR”或 “INFO”
  test-before-use: 如果為true,在每個連線被測試前都會服務這個連線,如果一個連線失敗,那麼將被丟棄,另一個連線將會被處理,如果所有連線都失敗,
一個新的連線將會被建立。否則將會丟擲一個SQLException異常。
  test-after-use: 如果為true,在每個連線被測試後都會服務這個連線,使其回到連線池中,如果連線失敗,那麼將被廢棄。
  trace: 如果為true,那麼每個被執行的SQL語句將會在執行期被log記錄(DEBUG LEVEL).你也可以註冊一個ConnectionListener (參看ProxoolFacade)得到這些資訊.

5、獲取JNDI資料來源

  如果應用配置在高效能的應用伺服器(如WebLogic或Websphere等)上,我們可能更希望使用應用伺服器本身提供的資料來源。應用伺服器的資料來源

使用JNDI開放呼叫者使用,Spring為此專門提供引用JNDI資源的JndiObjectFactoryBean類。

一個簡單的配置片段:

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">       
    <property name="jndiName" value="java:comp/env/jdbc/sample"/>       
</bean> 

使用jee名稱空間引用JNDI資料來源的配置片段:

  Spring 為獲取J2EE資源提供了一個jee名稱空間,通過jee名稱空間,可以有效地簡化J2EE資源的引用

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:jee=http://www.springframework.org/schema/jee 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd 
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
      
    <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/sample"/>
  
</beans>

6、Spring的資料來源實現類

  Spring本身也提供了一個簡單的資料來源實現類DriverManagerDataSource ,它位於org.springframework.jdbc.datasource包中。這個類實現了

javax.sql.DataSource介面,但 它並沒有提供池化連線的機制,每次呼叫getConnection()獲取新連線時,只是簡單地建立一個新的連線。因此,

這個資料來源類比較適合在單元測試 或簡單的獨立應用中使用,因為它不需要額外的依賴類。

DriverManagerDataSource ds = new DriverManagerDataSource ();       
ds.setDriverClassName("com.mysql.jdbc.Driver");       
ds.setUrl("jdbc:mysql://localhost:3306/sampledb");       
ds.setUsername("root");       
ds.setPassword("1234");       
Connection actualCon = ds.getConnection();

7、總結 
  不管採用何種持久化技術,都需要定義資料來源。Spring附帶了兩個資料來源的實現類包,你可以自行選擇進行定義。在實際部署時,我們可能會直接採用

應用伺服器本身提供的資料來源,這時,則可以通過JndiObjectFactoryBean或jee名稱空間引用JNDI中的資料來源。