記錄一波由會話堵塞導致tomcat應用故障事件


一、故障基本信息

發生時間

消除時間

故障歷時

故障類別

影響

2018-5-17 18:14:30

2018-05-18 08:58:15

16小時

應用故障

業務癱瘓,用戶投訴

 

二、故障現象

APP無法登陸,導致大面積投訴。

 

三、故障分析

1.查看系統2018-5-17 17:23:47時catalina日志顯示 ORA-00060等待資源時檢測到死鎖,且2018-5-17 18:11后無日志生成。

 

2.查看數據庫顯示與2018-05-17 17:23:12分時產生死鎖現象,生成數據報告,分析如下:

 

3.tomcat應用日志2018.5.17號存在疑似內存泄漏告警

五月 17, 2018 4:56:51 下午 org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc

嚴重: The web application [/manage] registered the JDBC driver [oracle.jdbc.OracleDriver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.   –內存泄漏告警

五月 17, 2018 4:56:51 下午 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads

嚴重: The web application [/manage] appears to have started a thread named [Dispatcher-Thread-3] but has failed to stop it. This is very likely to create a memory leak.

五月 17, 2018 4:56:51 下午 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads

嚴重: The web application [/manage] appears to have started a thread named [oracle.jdbc.driver.BlockSource.ThreadedCachingBlockSource.BlockReleaser] but has failed to stop it. This is very likely to create a memory leak.

五月 17, 2018 4:56:51 下午 org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks

嚴重: The web application [/manage] created a ThreadLocal with key of type [net.sf.json.AbstractJSON.CycleSet] (value [net.sf.json.AbstractJSON$CycleSet@73c791f]) and a value of type [java.lang.ref.SoftReference] (value [java.lang.ref.SoftReference@51484b24]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.

五月 17, 2018 4:56:51 下午 org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks

注:Java不需要管理內存的分配和釋放,一切由JVM自己來進行處理,當Java對象不再被應用時,等到堆內存不夠用時JVM會進行GC處理,清除這些對象占用的堆內存空間,但是如果對象一直被應用,那么JVM是無法對其進行GC處理的,那么我們創建新的對象時,JVM就沒有辦法從堆中獲取足夠的內存分配給此對象,這時就會導致內存溢出(OOM)。出現OOM原因,一般都是因為不斷的往容器里存放對象,然而容器沒有相應的大小限制或清除機制,這樣就容易導致OOM。

4.oracle awr性能報告(SQL部份截取)

 

1)      上面是sql語句執行時間排序,主要是更新商家信息賬戶信息表及賬戶系統賬戶信息表余額,分別excutions執行了300多次,Elapsed Time per Exec (s)平均一個update執行時間(單位:秒),即每次update 5分鍾左右。

2)      第1個sql:update PAY_CST_ACC set PCA_TOTALBANLANCE =( PCA_TOTALBANLANCE-:1 ), PCA_AVABANLANCE =(PCA_AVABANLANCE-:2 ) where PCA_CSTNO =:3 and PCA_USERACC=:4,花了325秒,即5分鍾左右,此時已經不正常。

因為oracle對數據增刪改查的操作機制,都需要將數據從磁盤調到內存操作,操作完commit提交后再根據一定規則刷到磁盤(如果該記錄原先已被其它會話操作調在內存,則直接從內存讀取)。連接會話操作數據都要占內存,如果應用眾多並發會話連接沒釋放,則到后面的連接內存不夠用了,等待前面的語句操作完釋放,如果出現多個並發操作同一記錄並鎖住其它連接要用的記錄等資源,則出現死鎖。具體處理建議請見第五章。

四、故障處理

臨時處理:分別Kill掉服務器tomcat進程,會話連接斷開,重啟應用問題解決。

五、故障預防建議

系統tomcat應用連庫配置路徑:xx/conf/context.xml,代碼如下:

<Resource name="jdbc/ebank_ds" type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:@xxxx:1521/實例名"
username="數據庫用戶名"
password="密碼"
maxActive="2000"
maxIdle="30"
maxWait="9000"/>

綜合上述應用日志提示內存泄漏告警以及和oracle數據庫日志提示檢測到等待資源死鎖,以及oracle awr性能報告。建議優化tomcat連接池參數,修改前建議先在測試和驗證環境模擬生產環境高並發連接測試,驗證有效后再修改生產配置。

增加和修改連接池參數如下:

<!--maxActive: 最大連接數量-->   
<property name="maxActive" value="2000"/> 
<!--minIdle: 最小空閑連接-->   
<property name="minIdle" value="5"/> 
<!--maxIdle: 最大空閑連接-->   
<property name="maxIdle" value="30"/> 
<!--initialSize: 初始化連接-->   
<property name="initialSize" value="20"/> 
<!-- 連接被泄露時是否打印 --> 
<property name="logAbandoned" value="true"/> 
<!--removeAbandoned: 是否自動回收超時連接-->   
<property name="removeAbandoned"  value="true"/> 
<!--removeAbandonedTimeout: 超時時間(以秒數為單位)-->   
<property name="removeAbandonedTimeout" value="10"/>
<!--maxWait: 超時等待時間以毫秒為單位--> 
<property name="maxWait" value="10000"/> 
<!-- 在空閑連接回收器線程運行期間休眠的時間值,以毫秒為單位. --> 
<property name="timeBetweenEvictionRunsMillis" value="10000"/> <!-- 在每次空閑連接回收器線程(如果有)運行時檢查的連接數量 --> <property name="numTestsPerEvictionRun" value="10"/> <!-- 1000 * 60 * 30 連接在池中保持空閑而不被空閑連接回收器線程--> <property name="minEvictableIdleTimeMillis" value="10000"/> <property name="validationQuery" value=" select 1 from dual "/>

站點修改應用tomcat連接池配置路徑:xx/ applicationContext.xml

<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@xx:1521:實例名"/>
<property name="username" value="數據庫用戶名" />
<property name="password" value="密碼" />
<property name="initialSize" value="5" />
<property name="maxActive" value="2000" />
<property name="defaultAutoCommit" value="true" /> 

修改成與賬戶系統一致的連接參數。

具體連接參數說明請參考tomcat 7官網鏈接說明:https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html

附:連接參數的幾點說明

maxActive="100"

表示並發情況下最大可從連接池中獲取的連接數。如果數據庫不是單獨,供一個應用使用,通過設置maxActive參數可以避免某個應用無限制的獲取連接對其他應用造成影響,如果一個數據庫只是用來支持一個應用那么maxActive理論上可以設置成該數據庫可以支撐的最大連接數。maxActive只是表示通過連接池可以並發的獲取的最大連接數。連接的獲取與釋放是雙向,當應用程序並發請求連接池時,連接池就需要從數據庫獲取連接,那么但應用程序使用完連接並將連接歸還給連接池時,連接池是否也同時將連接歸還給數據庫呢?很顯然答案是否定的,如果那樣的話連接池就變得多此一舉,不但不能提高性能,反而會降低性能,那么但應用成歸還連接后,連接池如何處理呢?

maxIdle="30"

如果在並發時達到了maxActive=100,那么連接池就必須從數據庫中獲取100個連接來供應用程序使用,當應用程序關閉連接后,由於maxIdle=30,因此並不是所有的連接都會歸還給數據庫,將會有30個連接保持在連接池種中,狀態為空閑。

minIdle=”2”

最小默認情況下並不生效,它的含義是當連接池中的連接少有minIdle,系統監控線程將啟動補充功能,一般情況下我們並不啟動補充線程。

問題:如何設置maxActivemaxIdle

理論上講maxActive應該設置成應用的最大並發數,這樣一來即便是在最大並發的情況下,應用依然能夠從連接池中獲取連接,但是困難時的是我們很難准確估計到最大並發數,設置成最大並發數是一種最優的服務質量保證,事實上,如果某個用戶登錄提示系統繁忙,那么在他再次登錄時,可能系統資源已經充足,對於xx系統我們建議將maxActive設置為系統注冊人數的十分之一到二十分之一之間。例如系統的注冊人數為1000,那么設置成50-100靠近100的數字,例如85或90。

    maxIdle對應的連接,實際上是連接池保持的長連接,這也是連接池發揮優勢的部分,理論上講保持較多的長連接,在應用請求時可以更快的響應,但是過多的連接保持,反而會消耗數據庫大量的資源,因此maxIdle也並不是越大越好,同上例我們建議將 maxIdle設置成50-100中靠近50的數字,例如55。這樣就能在兼顧最大並發同時,保持較少的數據庫連接,而且在絕大多情況,能夠為應用程序提供最快的相應速度。

removeAbandoned="true"

removeAbandonedTimeout="60"

logAbandoned="true"

有時粗心的程序編寫者在從連接池中獲取連接使用后忘記了連接的關閉,這樣連池的連接就會逐漸達到maxActive直至連接池無法提供服務。現代連接池一般提供一種“智能”的檢查,但設置了removeAbandoned="true"時,當連接池連接數到達(getNumIdle() < 2) and (getNumActive() > getMaxActive() - 3)時便會啟動連接回收,那種活動時間超過removeAbandonedTimeout="60"的連接將會被回收,同時如果logAbandoned="true"設置為true,程序在回收連接的同時會打印日志。removeAbandoned是連接池的高級功能,理論上這中配置不應該出現在實際的生產環境,因為有時應用程序執行長事務,可能這種情況下,會被連接池誤回收,該種配置一般在程序測試階段,為了定位連接泄漏的具體代碼位置,被開啟,生產環境中連接的關閉應該靠程序自己保證。

 


免責聲明!

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



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