解決Tomcat數據連接池無法釋放


近段時間,公司的檢測中心報表系統(SMC)的開發人員時不時找到我,說用戶老是出現無法登錄的情況。前些日子因為手頭上 有Jboss集群的測試工作,發現用戶不能登錄時,都是在Tomcat中將這個項目Reload一下就好了,不過只是治標而已,因為大概幾個小時之后又會 再次出現無法登錄的情況。

今天上午,開發人員小毛又找到我,要我協助將這個問題根治一下,拖太久用戶難保不投訴。

簡單分析了一下,每次Reload一下就能解決無法登錄的情況,自然而然就想到是不是session有問題呢?於是到Tomcat的manager界面看了下,發現並沒有出現session粘滯暴漲的情況。

本來可以打開jconsole看看的,正好想起了之前用過的Tomcat檢測工具:probe,於是直接從其他機器上scp了一個probe.war,丟到了webapps下面自動部署。

部署完之后,打開了probe網頁管理后台發現smc項目的實時數據庫連接數很高,而且只增不減!這個系統的數據池大小設置為200,此時已經是100+了,而且一直只升不降。好吧,當數據連接數達到200時,問題肯定會再次出現的。

於是我將這個問題告訴了小毛,要他自己去修改連接池釋放機制(這里用的是項目單獨設定的參數)。他說試過了,沒有用,問下我有沒有辦法。

我這人記性一直欠佳,也很少去記憶一些參數設置,問我么?還我也只能問BD、GG了。。。

最終在強大的搜索引擎的幫助下,找到了相關參數說明,通過參考修改后成功解決了問題!

Tomcat連接池無法釋放的解決方法:

編輯項目的連接池配置文件:context.xml,參考下面的【數據庫連接設置】參數說明,按照實際情況調整好各項數值,尤其是Maxidle和maxActive。並記得加上removeAbandoned=true 相關釋放參數即可,我們這最終設置好的context.xml如下所示:

<Resource name="jdbc/smc" type="javax.sql.DataSource" username="user" password="password" driverClassName="oracle.jdbc.driver.OracleDriver" maxIdle="50" maxWait="2000" removeAbandoned="true" removeAbandonedTimeout="180" validationQuery="select * from dual " url="jdbc:oracle:thin:@192.168.7.98:1521:dw" maxActive="200"/>
1
2
3
4
5
6
7
8
9
10
11
12
<Resource name="jdbc/smc"  
          type="javax.sql.DataSource"  
          username="user"  
          password="password"  
          driverClassName="oracle.jdbc.driver.OracleDriver"  
           maxIdle="50"  
           maxWait="2000"  
           removeAbandoned="true"  
           removeAbandonedTimeout="180"  
           validationQuery="select * from dual "  
               url="jdbc:oracle:thin:@192.168.7.98:1521:dw"  
         maxActive="200"/>
數據庫連接設置參考:

#數據庫連接設置 jdbc.driverClassName=oracle.jdbc.driver.OracleDriver jdbcjdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:DBSERVER jdbc.username=user jdbc.password=pass #<!-- 初始化連接 --> dataSource.initialSize=10 #<!-- 最大空閑連接 --> dataSource.maxIdle=20 #<!-- 最小空閑連接 --> dataSource.minIdle=5 #最大連接數量 dataSource.maxActive=50 #是否在自動回收超時連接的時候打印連接的超時錯誤 dataSource.logAbandoned=true #是否自動回收超時連接 dataSource.removeAbandoned=true #超時時間(以秒數為單位) dataSource.removeAbandonedTimeout=180 #<!-- 超時等待時間以毫秒為單位 --> dataSource.maxWait=1000
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#數據庫連接設置  
jdbc.driverClassName=oracle.jdbc.driver.OracleDriver  
jdbcjdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:DBSERVER  
jdbc.username=user  
jdbc.password=pass  
  
#<!-- 初始化連接 -->  
dataSource.initialSize=10  
  
#<!-- 最大空閑連接 -->  
dataSource.maxIdle=20  
  
#<!-- 最小空閑連接 -->  
dataSource.minIdle=5  
  
#最大連接數量  
dataSource.maxActive=50  
  
#是否在自動回收超時連接的時候打印連接的超時錯誤  
dataSource.logAbandoned=true  
  
#是否自動回收超時連接  
dataSource.removeAbandoned=true  
  
#超時時間(以秒數為單位)  
dataSource.removeAbandonedTimeout=180  
  
#<!-- 超時等待時間以毫秒為單位 -->  
dataSource.maxWait=1000
附上作者的原文說明:

在配置DBCP連接池時,主要難以理解的主要有:removeAbandoned 、logAbandoned、removeAbandonedTimeout、maxWait這四個參數,設置了rmoveAbandoned=true 那么在getNumActive()快要到getMaxActive()的時候,系統會進行無效的Connection的回收,回收的 Connection為removeAbandonedTimeout(默認300秒)中設置的秒數后沒有使用的Connection,激活回收機制好像 是getNumActive()=getMaxActive()-2。

如果開啟"removeAbandoned",那么連接在被認為泄露時可能被池回收. 這個機制在(getNumIdle() < 2) and (getNumActive() > getMaxActive() - 3)時被觸發.

舉例:當maxActive=20, 活動連接為18,空閑連接為1時可以觸發"removeAbandoned".但是活動連接只有在沒有被使用的時間超過"removeAbandonedTimeout"時才被刪除,默認300秒.在resultset中游歷不被計算為被使用.

logAbandoned=true的話,將會在回收事件后,在log中打印出回收Connection的錯誤信息,包括在哪個地方用了Connection卻忘記關閉了,在調試的時候很有用。

在這里私人建議maxWait的時間不要設得太長,maxWait如果設置太長那么客戶端會等待很久才激發回收事件。
————————————————
版權聲明:本文為CSDN博主「ronon77」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/ronon77/article/details/84730306


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM