Spring
一、Proxool連接池簡介及其配置屬性概述
Proxool是一種Java數據庫連接池技術。是sourceforge下的一個開源項目,這個項目提供一個健壯、易用的連接池,最為關鍵的是這個連接池提供監控的功能,方便易用,便於發現連接泄漏的情況。
目前是和DBCP以及C3P0一起,最為常見的三種JDBC連接池技術。
日前,Hibernate官方宣布由於Bug太多不再支持DBCP,而推薦使用 Proxool或C3P0。
要使用Proxool首先要導入Proxool.jar,此jar包可以在下載的Hibernate包中hibernate-release-4.1.7.Final\lib\optional\proxool\中找到;也可以到官網:http://nchc.dl.sourceforge.net/sourceforge/proxool/proxool-0.9.1-source.zip下載它的源碼,下載完后解壓,把proxool.jar和proxool-cglib.jar放入你要配置的項目的lib目錄下. 。
simultaneous-build-throttle:
是指在任一時刻,可以(同時)建立的最大連接數,也就是說,就是已經請求的、但還沒可用的新連接數量。因為連接可以用多線程建立,從決定要建立連接到連接 可用是需要一定時間的,所以我們需要一些方式來避免大量的線程想同時建立連接。(我們本應該找一個更聰明的方式來解決這個問題,總有一天我們會找到的)默 認值是 10
當我使用140個用戶,進行壓力測試時,發現偶爾,會有多於10個要求同時建立連接的請求,當請求數量超過限定的數值時,會出現連接失敗的情況。
因此結論就是,當數據庫並發連接可能會比較高的應用,這個值應該適當的設大一點。
如果並發請求很高,可能出現的bug為
Caused by: java.sql.SQLException: We are already in the process of making 11 connections and the number of simultaneous builds has been throttled to 10
maximum-active-time:
如果一個線程活動時間超過這個數值,線程會被殺死。所以要確保這個數值設置得比最慢的響應時間長。默認是5分鍾。守護進程會把連接池中多余的可用線程(未 用的、超過這個時間的)殺死,最終保留的連接數量就是minimum-connection-count規定的數量。守護進程會根據house- keeping-sleep-time參數設置的時間隔定時檢查。
maximum-connection-lifetime:
指一個連接最大的存活時間(毫秒為單位),超過這個時間,連接會被殺死。默認值是4小時。
overload-without-refusal-lifetime:
這個參數幫助我們確定連接池的狀態,如果在這個時間閥值內(單位為毫秒)拒絕了一個連接,就認為是過載了。默認值是60。
alias:數據源的別名
driver-url:url連接串,須確定用戶名和密碼
driver-class:驅動名
username:用戶名(proxool沒有使用,但是不能沒有)
password:密碼(proxool沒有使用,但是不能沒有)
maximum-new-connections:沒有空閑連接可以分配而在隊列中等候的最大請求數,超過這個請求數的用戶連接就不會被接受
test-before-use:
如果連接池在運行當中,出現網絡或者數據庫故障而無法連接到數據庫,在恢復正常以后,由於連接是在連接池中持久保存的,會出現連接仍然不可用的情況,這時連接池里的連接實際上都是壞連接,怎么讓連接池可以自動重連清除這些壞連接呢? 只要配置了test-before-use 參數,即每次取出連接都檢查連接是否可用,就可以做到讓連接池實現在故障恢復后自動重連接
需要注意一點,對於Mysql數據庫還必須在連接參數里加上autoReconnect=true 參數,否則即使打開了test-before-use 參數,仍然不能重連接!
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:
proxool自動偵察各個連接狀態的時間間隔(毫秒),偵察到空閑的連接就馬上回收,超時的銷毀 默認30秒)
house keeper 保留線程處於睡眠狀態的最長時間,house keeper 的職責就是檢查各個連接的狀態,並判斷是否需要銷毀或者創建.
house-keeping-test-sql:
如果發現了空閑的數據庫連接.house keeper 將會用這個語句來測試.這個語句最好非常快的被執行.如果沒有定義,測試過程將會被忽略。
一般mysql可用select SYSDATE ,Oracle可用 select sysdate from dual 或者 select 1 from dual
injectable-connection-interface: 允許proxool實現被代理的connection對象的方法.
injectable-statement-interface: 允許proxool實現被代理的Statement 對象方法.
injectable-prepared-statement-interface: 允許proxool實現被代理的PreparedStatement 對象方法.
injectable-callable-statement-interface: 允許proxool實現被代理的CallableStatement 對象方法.
jndi-name: 數據源的名稱
maximum-active-time: 如果housekeeper 檢測到某個線程的活動時間大於這個數值.它將會殺掉這個線程.所以確認一下你的服務器的帶寬.然后定一個合適的值.默認是5分鍾.
maximum-connection-count:
The maximum number of connections to the database. Default is 15.
最大的數據庫連接數.默認是15
minimum-connection-count: 最小的數據庫連接數,默認是5
prototype-count:
連接池中可用的連接數量.如果當前的連接池中的連接少於這個數值.新的連接將被建立(假設沒有超過最大可用數).例如.我們有3個活動連接2個可用連接,而我們的prototype-count是4,那么數據庫連接池將試圖建立另外2個連接.這和 minimum-connection-count不同. minimum-connection-count把活動的連接也計算在內.prototype-count 是spare connections 的數量.
statistics: 連接池使用狀況統計。 參數“10s,1m,1d”
statistics-log-level: 日志統計跟蹤類型。 參數“ERROR”或 “INFO”
trace: 如果為true,那么每個被執行的SQL語句將會在執行期被log記錄(DEBUG LEVEL).你也可以注冊一個ConnectionListener (參看ProxoolFacade)得到這些信息.
verbose: 詳細信息設置。 參數 bool 值
二、Spring中配置Proxool連接池管理數據源方式與步驟
方式一、
在Spring的"applicationContext.xml"中的dataSource bean定義——
<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/dbname?user=yourname&password=yourpass</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屬性似乎沒有什么用。無論提供什么,它都會以空用戶名、密碼去連接數據庫。這可能是Proxool RC0.93的一個bug,實在讓人惱火,不知道最新的0.9.1有沒有fix這個bug。不過配置中的user,password兩個屬性還必須設置,否則hibernate會報空指針錯誤。
方式二:
步驟一:在Spring的"applicationContext.xml"中的dataSource bean定義——
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>org.logicalcobwebs.proxool.ProxoolDriver</value>
</property>
<property name="url">
<value>proxool.Pool_dbname</value>
</property>
</bean>
步驟二、預先在"web.xml"先配置好Proxool連接池,配置如下:
<!--管理proxool配置文件-->
<servlet>
<servlet-name>proxoolServletConfigurator</servlet-name>
<servlet-class> org.logicalcobwebs.proxool.configuration.ServletConfigurator
</servlet-class>
<init-param>
<param-name>xmlFile</param-name>
<param-value>WEB-INF/proxool.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!--查看proxool運行情況,也可以不作配置的
<servlet>
<servlet-name>proxooladmin</servlet-name>
<servlet-class>
org.logicalcobwebs.proxool.admin.servlet.AdminServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>proxooladmin</servlet-name>
<url-pattern>/proxooladmin</url-pattern>
</servlet-mapping>
-->
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>
org.springframework.web.context.ContextLoaderServlet
</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
注意: 把<load-on-startup>的值設為1,值越小級別就越高,就先被加載初始化。一定要先於applicationContext.xml的加載;第二種方式下Spring的上下文加載如果想使用listener方式(Struts2要求),
則與連接池有關的Bean全得延遲初始化。因為listener比servlet優先初始化,
如果相關Bean不是lazy-init的話,則啟動服務器時會出現Bean找不到連接定義的異常:Problem
org.logicalcobwebs.proxool.ProxoolException: Attempt to refer to a unregistered pool by its
alias 'db' 。
listener方式如下:
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
步驟三、在/WEB-INF/下添加proxool的配置文件:proxool.xml
proxool的配置文件可以采用xmlFile"proxool.xml"或者propertyFile"proxool.properties"
"proxool.xml"格式如下:
<?xml version="1.0" encoding="UTF-8"?>
<proxool-config>
<proxool>
<alias>Pool_dbname</alias>
<driver-url>jdbc:mysql://localhost:3306/dbname</driver-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<driver-properties>
<property name="user" value="yourname"/>
<property name="password" value="yourpass"/>
</driver-properties>
<house-keeping-sleep-time>60000</house-keeping-sleep-time>
<maximum-connection-count>20</maximum-connection-count>
<minimum-connection-count>2</minimum-connection-count>
<prototype-count>0</prototype-count>
<simultaneous-build-throttle>20</simultaneous-build-throttle>
<house-keeping-test-sql>select CURRENT_DATE</house-keeping-test-sql>
<statistics>15s,10m,1d</statistics>
<statistics-log-level>INFO</statistics-log-level>
</proxool>
<proxool>
<!--可以配置多個庫-->
</proxool>
</proxool-config>
"proxool.properties"格式如下:
jdbc-0.proxool.alias=Pool_dbname
jdbc-0.proxool.driver-url=jdbc:mysql://localhost:3306/dbname
jdbc-0.proxool.driver-class=com.mysql.jdbc.Driver
jdbc-0.user=yourname
jdbc-0.password=yourpass
jdbc-0.proxool.house-keeping-sleep-time=60000
jdbc-0.proxool.house-keeping-test-sql=select CURRENT_DATE
jdbc-0.proxool.maximum-connection-count=10
jdbc-0.proxool.minimum-connection-count=3
jdbc-0.proxool.maximum-connection-lifetime=18000000
jdbc-0.proxool.prototype-count=3
jdbc-0.proxool.simultaneous-build-throttle=10
jdbc-0.proxool.recently-started-threshold=60000
jdbc-0.proxool.overload-without-refusal-lifetime=50000
jdbc-0.proxool.maximum-active-time=60000
jdbc-0.proxool.verbose=true
jdbc-0.proxool.trace=true
jdbc-0.proxool.fatal-sql-exception=Fatal error
jdbc-2.proxool.alias=Pool_dbname2
……
<!--可以配置多個庫-->
至此,已完成所有配置。
-----------------------------------------------------------
個人比較傾向於第二種配置方式,
1:可以避免在Spring的"applicationContext.xml"中寫一大堆參數,
尤其是避免了driverUrl中帶用戶名密碼(這會顯示在proxool包中帶的
org.logicalcobwebs.proxool.admin.servlet.AdminServlet輸出的頁面中)
2:proxool連接池可以在tomcat啟動時就初始化好,可以提高第一次訪問web時的連接速度。
三、更詳細的配置示例
1、更詳細的proxool.xml的配置屬性說明:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
Properties for Proxool Configurator testing. Defines the same parameters as
TestHelper.buildCompleteAlternativeProperties()
-->
<something-else-entirely xmlns="http://sumthin.else.entirely" xmlns:proxool="The latest version is available at http://proxool.sourceforge.net/xml-namespace">
<proxool:proxool>
<proxool:alias>xml-test-ns</proxool:alias>
<proxool:driver-url>jdbc:hsqldb:db/test</proxool:driver-url>
<proxool:driver-class>org.hsqldb.jdbcDriver</proxool:driver-class>
<proxool:driver-properties>
<proxool:property name="user" value="sa"/>
<proxool:property name="password" value=""/>
</proxool:driver-properties>
<proxool:house-keeping-sleep-time>40000</proxool:house-keeping-sleep-time>
<proxool:house-keeping-test-sql>select CURRENT_DATE</proxool:house-keeping-test-sql>
<proxool:maximum-connection-count>10</proxool:maximum-connection-count>
<proxool:minimum-connection-count>3</proxool:minimum-connection-count>
<proxool:maximum-connection-lifetime>18000000</proxool:maximum-connection-lifetime>
<!-- 5 hours -->
<proxool:simultaneous-build-throttle>5</proxool:simultaneous-build-throttle>
<proxool:recently-started-threshold>40000</proxool:recently-started-threshold>
<proxool:overload-without-refusal-lifetime>50000</proxool:overload-without-refusal-lifetime>
<proxool:maximum-active-time>60000</proxool:maximum-active-time>
<proxool:verbose>true</proxool:verbose>
<proxool:trace>true</proxool:trace>
<proxool:fatal-sql-exception>Fatal error</proxool:fatal-sql-exception>
<proxool:prototype-count>2</proxool:prototype-count>
</proxool:proxool>
<nothing-to-do-with-proxool>
<proxool:proxool>
<proxool:alias>xml-test-ns-2</proxool:alias>
<proxool:driver-url>jdbc:hsqldb:db/test</proxool:driver-url>
<proxool:driver-class>org.hsqldb.jdbcDriver</proxool:driver-class>
<proxool:driver-properties>
<proxool:property name="user" value="sa"/>
<proxool:property name="password" value=""/>
</proxool:driver-properties>
<proxool:house-keeping-sleep-time>40000</proxool:house-keeping-sleep-time>
<proxool:house-keeping-test-sql>select CURRENT_DATE</proxool:house-keeping-test-sql>
<proxool:maximum-connection-count>10</proxool:maximum-connection-count>
<proxool:minimum-connection-count>3</proxool:minimum-connection-count>
<proxool:maximum-connection-lifetime>18000000</proxool:maximum-connection-lifetime>
<!-- 5 hours -->
<proxool:simultaneous-build-throttle>5</proxool:simultaneous-build-throttle>
<proxool:recently-started-threshold>40000</proxool:recently-started-threshold>
<proxool:overload-without-refusal-lifetime>50000</proxool:overload-without-refusal-lifetime>
<proxool:maximum-active-time>60000</proxool:maximum-active-time>
<proxool:verbose>true</proxool:verbose>
<proxool:trace>true</proxool:trace>
<proxool:fatal-sql-exception>Fatal error</proxool:fatal-sql-exception>
<proxool:prototype-count>2</proxool:prototype-count>
</proxool:proxool>
</nothing-to-do-with-proxool>
</something-else-entirely>
屬性列表說明:
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: 略
jmx-agent-id: 略
jndi-name: 數據源的名稱
maximum-active-time: 如果housekeeper 檢測到某個線程的活動時間大於這個數值.它將會殺掉這個線程.所以確認一下你的服務器的帶寬.然后定一個合適的值.默認是5分鍾.
maximum-connection-count: 最大的數據庫連接數.
maximum-connection-lifetime: 一個線程的最大壽命.
minimum-connection-count: 最小的數據庫連接數
overload-without-refusal-lifetime: 略
prototype-count: 連接池中可用的連接數量.如果當前的連接池中的連接少於這個數值.新的連接將被建立(假設沒有超過最大可用數).例如.我們有3個活動連接2個可用連接,而我們的prototype-count是4,那么數據庫連接池將試圖建立另外2個連接.這和 minimum-connection-count不同. minimum-connection-count把活動的連接也計算在內.prototype-count 是spare connections 的數量.
recently-started-threshold: 略
simultaneous-build-throttle: 略
statistics: 連接池使用狀況統計。 參數“10s,1m,1d”
statistics-log-level: 日志統計跟蹤類型。 參數“ERROR”或 “INFO”
test-before-use: 略
test-after-use: 略
trace: 如果為true,那么每個被執行的SQL語句將會在執行期被log記錄(DEBUG LEVEL).你也可以注冊一個ConnectionListener (參看ProxoolFacade)得到這些信息.
verbose: 詳細信息設置。 參數 bool 值
2.更詳細的在web.xml中配置管理proxool的servlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>ServletConfigurator</servlet-name>
<servlet-class>
org.logicalcobwebs.proxool.configuration.ServletConfigurator
</servlet-class>
<init-param>
<param-name>xmlFile</param-name>
<param-value>WEB-INF/proxool.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>Admin</servlet-name>
<servlet-class>
org.logicalcobwebs.proxool.admin.servlet.AdminServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Admin</servlet-name>
<url-pattern>/admin</url-pattern>
</servlet-mapping>
<!-- 配置受保護域,只有Tomcat管理員才能察看連接池的信息 -->
<security-constraint>
<web-resource-collection>
<web-resource-name>proxool</web-resource-name>
<url-pattern>/admin</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>manager</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>proxool manager Application</realm-name>
</login-config>
<security-role>
<description>The role that is required to log in to the Manager Application</description>
<role-name>manager</role-name>
</security-role>
<error-page>
<error-code>401</error-code>
<location>/401.jsp</location>
</error-page>
</web-app>