一、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>