帆軟報表FineReport中數據連接的JDBC連接池屬性問題
連接池原理
在帆軟報表FineReport中,連接池主要由三部分組成:連接池的建立、連接池中連接使用的治理、連接池的關閉。下面就着重討論這三部分及連接池的配置問題。
連接池技術的核心思想,是連接復用,通過建立一個數據庫連接池以及一套連接使用、分配、治理策略,使得該連接池中的連接可以得到高效、安全的復用,避免了數據庫連接頻繁建立、關閉的開銷。
另外,由於對JDBC中的原始連接進行了封裝,從而方便了數據庫應用對於連接的使用(特別是對於事務處理),提高了開發效率,也正是因為這個封裝層的存在,隔離了應用的本身的處理邏輯和具體數據庫訪問邏輯,使應用本身的復用成為可能。
應用程序中建立的連接池其實是一個靜態的。所謂靜態連接池是指連接池中的連接在系統初始化時就已分配好,且不能隨意關閉連接。Java中提供了很多容器類可以方便的構建連接池,如:Vector、Stack、Servlet、Bean等,通過讀取連接屬性文件Connections.properties與數據庫實例建立連接。在系統初始化時,根據相應的配置創建連接並放置在連接池中,以便需要使用時能從連接池中獲取,這樣就可以避免連接隨意的建立、關閉造成的開銷。
連接池管理策略是連接池機制的核心。當連接池建立后,如何對連接池中的連接進行管理,解決好連接池內連接的分配和釋放,對系統的性能有很大的影響。連接的合理分配、釋放可提高連接的復用,降低了系統建立新連接的開銷,同時也加速了用戶的訪問速度。下面介紹連接池中連接的分配、釋放策略。
連接池的分配、釋放策略對於有效復用連接非常重要,我們采用的方法是一個很有名的設計模式:Reference Counting(引用記數)。該模式在復用資源方面應用的非常廣泛,把該方法運用到對於連接的分配釋放上,為每一個數據庫連接,保留一個引用記數,用來記錄該連接的使用者的個數。
具體實現方法如下:
當客戶請求數據庫連接時,首先查看連接池中是否有空閑連接(指當前沒有分配出去的連接)。如果存在空閑連接,則把連接分配給客戶並作相應處理(即標記該連接為正在使用,引用計數加1)。如果沒有空閑連接,則查看當前所開的連接數是不是已經達到maxConn(最大連接數),如果沒達到就重新創建一個連接給請求的客戶;如果達到就按設定的maxWaitTime(最大等待時間)進行等待,如果等待maxWaitTime后仍沒有空閑連接,就拋出無空閑連接的異常給用戶。
當客戶釋放數據庫連接時,先判斷該連接的引用次數是否超過了規定值,如果超過就刪除該連接,並判斷當前連接池內總的連接數是否小於minConn(最小連接數),若小於就將連接池充滿;如果沒超過就將該連接標記為開放狀態,可供再次復用。可以看出正是這套策略保證了數據庫連接的有效復用,避免頻繁地建立、釋放連接所帶來的系統資源開銷。
當應用程序退出時,應關閉連接池,此時應把在連接池建立時向數據庫申請的連接對象統一歸還給數據庫(即關閉所有數據庫連接),這與連接池的建立正好是一個相反過程。
連接池分配一個連接后如定義一個數據集,點擊預覽,執行完對應的sql語句會將所占用的連接歸還連接池。
數據庫連接池中到底要放置多少個連接,才能使系統的性能更佳,用minConn和maxConn來限制。
minConn是當應用啟動的時候連接池所創建的連接數,假如過大啟動將變慢,但是啟動后響應更快;假如過小啟動加快,但是最初使用的用戶將因為連接池中沒有足夠的連接不可避免的延緩了執行速度。因此應該在開發的過程中設定較小minConn,而在實際應用的中設定較大minConn。maxConn是連接池中的最大連接數,可以通過反復試驗來確定此飽和點。
為此在連接池類ConnectionPool中加入兩個方法getActiveSize()和getOpenSize(),ActiveSize 表示某一時間有多少連接正被使用,OpenSize表示連接池中有多少連接被打開,反映了連接池使用的峰值。將這兩個值在日志信息中反應出來, minConn的值應該小於平均ActiveSize,而maxConn的值應該在activeSize和OpenSize之間。
連接池屬性
1. 問題描述
FineReport連接池屬性,使用的是DBCP連接池,下面介紹其設置方法及其屬性中各參數的意義;如果訪問模板時,報連接超時、等待狀態,警告如下:
1. 警告:Cannot get a connection, pool error Timeout waiting for idle object
2. at com.fr.third.org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:114)
3. at com.fr.third.org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
4. at com.fr.data.pool.MemoryConnection.create(Unknown Source)
5. at com.fr.data.impl.JDBCDatabaseConnection.createConnection(Unknown Source)
則需要把相應連接數調大。
2. 設置方法
點擊服務器>定義數據連接,如下圖所示,點擊連接池屬性,彈出連接池屬性編輯框:

這里的信息都保存在%FR_HOME%\WebReport\WEB-INF\resources\datasource.xml文件下:
<DBCPAttr
initialSize="1"
maxActive="200"
maxIdle="100"
minIdle="2"
maxWait="1000"
validationQuery="q"
testOnBorrow="false"
testOnReturn="true"
testWhileIdle="true"
timeBetweenEvictionRunsMillis="1000"
numTestsPerEvictionRun="2"
minEvictableIdleTimeMillis="18005000"/>
| 名稱 |
舉例 |
含義 |
| 初始化連接數 |
initialSize="1" |
初始化線程數,開始自動建立一個與數據庫的連接 |
| 最大活動連接數 |
maxActive="200" |
可以從對象池中取出的對象最大個數,為0表示沒有限制 |
| 最大空閑連接數 |
maxIdle="100" |
最大等待連接中的數量,設為負數則沒有限制(對象池中對象最大個數) |
| 最小空閑連接數 |
minIdle="2" |
對象池中對象最小個數 |
| 最大等待時間(毫秒) |
maxWait="1000" |
最大等待時間,單位為ms,超出時間會丟出錯誤信息 |
| SQL驗證查詢 |
validationQuery="SQL語句" |
驗證連接是否成功,SQL和SELECT指令至少要返回一行 |
| 獲取連接前檢驗 |
testOnBorrow="false" |
取得對象時是否進行驗證,檢查對象是否有效,默認為false |
| 歸還連接前檢驗 |
testOnReturn="true" |
返回對象時是否進行驗證,檢查對象是否有效,默認為false |
| 開啟空閑回收器檢驗 |
testWhileIdle="true" |
空閑時是否進行驗證,檢查對象是否有效,默認為false |
| 空閑連接回收器休眠時間(毫秒) |
timeBetweenEvictionRunsMillis="1000" |
失效檢查線程運行時間間隔,如果小於等於0,不會啟動檢查線程 |
| 空閑連接回收檢查數 |
numTestsPerEvictionRun="2" |
失效檢查線程運行次數 |
| 保持空閑最小時間 |
minEvictableIdleTimeMillis="18005000" |
大於0,進行連接空閑時間判斷,或為0,對空閑的連接不進行驗證 |
最大活動連接數設置超過數據庫中的連接數目,只能按照數據庫中的連接數目為准,如想調至最大,則也要調整數據庫中的連接數目,參考文檔連接池滿問題中的解決方案。
連接池滿問題
1. 問題描述
若日志報ORA-12519 TNS:no appropriate service handler found,是數據庫連接失敗的錯誤,12519錯誤是監聽不能提供服務。
2. 原因
原因是我們定義數據連接后,點擊連接時,此時會從用掉一個連接池中的一個連接。而在定義數據集后,點擊預覽按鈕,此時連接池就會分配連接,可能會使用之前那個連接(之前的連接已釋放),或分配一個其他的連接或新建一個連接。若此時連接池所有連接都已用完,就會報如下錯誤:

當客戶請求數據庫連接時,首先是查看連接池中是否有空閑連接(指當前沒有分配出去的連接)。假如存在空閑連接,則把連接分配給用戶,並作相應的處理(即標記該連接為正在使用,引用計數加1)。假如沒有空閑連接,則查看當前所開的連接數是不是已經達到maxConn(最大連接數),若沒達到就重新創建一個連接給請求的客戶;若達到就按設定的maxWaitTime(最大等待時間)進行等待;若等待maxWaitTime后,仍沒有空閑連接,就拋出無空閑連接的異常給用戶。
3. 解決方案
若您在FineReport連接池屬性的設置中,已將最大連接數設置得過大,還出現如上的報錯,此時通常就是數據庫進程(processes)達到上限導致的,可增大數據庫中的連接數目來解決此問題。如下在數據庫中修改最大連接數:
Select count(*) from v$process查看當前的連接數
Select value from v$parameter where name='processes'查看數據庫允許的最大連接數
Alter system set processes =300 scope = spfile;修改最大連接數
重啟數據庫,再查詢最大連接數,數字改變就表示已修改成功。
說明:當客戶釋放數據庫連接時,先判定該連接的引用次數是否已超過規定值,假如超過就刪除該連接,並判定當前連接池內總的連接數是否小於minConn(最小連接數),若小於就將連接池布滿;假如沒超過就將該連接標記為開放狀態,可供再次復用。可看出正是這套策略保證了數據庫連接的有效復用,避免頻繁地建立、釋放連接所帶來的系統資源開銷。
