proxool Java數據庫連接池配置及使用

背景

公司一個14年的項目WebService項目中使用proxool來做數據連接池,使用mybatis進行數據庫的操作,使用spring進行管理,所有在這裏學習一下spring下的proxool。

Proxool是一種Java數據庫連接池技術。是sourceforge下的一個開源項目,這個項目提供一個健壯、易用的連接池,最爲關鍵的是這個連接池提供監控的功能,方便易用,便於發現連接泄漏的情況。

1、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&amp;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><!--配置了proxool的數據庫連接的名字<property name="url">要配置成 proxool. + proxool.xml中的別名-->
    </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>

項目中的代碼:

    <!--管理proxool配置文件-->
   <!--     <context-param>  
        <param-name>proxoolConfigLocation</param-name>  
        <param-value>WEB-INF/proxool.xml</param-value>  
    </context-param>  
    
    <listener>  
        <listener-class>org.logicalcobwebs.proxool.configuration.ListenerConfigurator</listener-class>  
    </listener>   -->

複製代碼

注意: 把<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方式如下:先初始化listenser再初始化servlet

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

複製代碼

設置連接屬性:

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 值

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 值

alias:數據源的別名
driver-url:url連接串,須確定用戶名和密碼
driver-class:驅動名
username:用戶名(proxool沒有使用,但是不能沒有)
password:密碼(proxool沒有使用,但是不能沒有)
maximum-connection-count:最大連接數(默認5個),超過了這個連接數,再有請求時,就排在隊列中等候,最大的等待請求數由maximum-new-connections決定
minimum-connection-count:最小連接數(默認2個)
house-keeping-sleep-time:proxool自動偵察各個連接狀態的時間間隔(毫秒),偵察到空閒的連接就馬上回收,超時的銷燬 默認30秒)
prototype-count:最少保持的空閒連接數(默認2個)
maximum-new-connections:有空閒連接可以分配而在隊列中等候的最大請求數,超過這個請求數的用戶連接就不會被接受
test-before-use和house-keeping-test-sql:測試用

三、更詳細的配置示例
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>

複製代碼

"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時的連接速度

 

https://www.cnblogs.com/wllyy189/archive/2008/10/15/1311560.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章