生產上Tomcat出現 Connection has already been closed.問題,但是在uat測試是好的!
遇見兩次:
1.某個程序dao中執行邏輯異常復雜,有時候需要執行一分多鍾,uat正常執行,生產上個別執行時間長的會出現Connection has already been closed!
2.某程序在service中注入dao,業務邏輯中獲取一批數據放在list中遍歷,每遍歷一次用dao直接調用方法,大概四五個dao的方法,過一會出現Connection has already been closed!
問題根本原因:
1.小伙伴配置時,會添加以下連接配置參數
removeAbandoned="true"
removeAbandonedTimeout="60"(removeAbandonedTimeout”(默認300秒))
logAbandoned="true"
有時候代碼中會有從連接池中獲取連接使用后忘記了連接的關閉,這樣連池的連接就會逐漸達到maxActive直至連接池無法getConnection。
連接池一般提供檢查功能,即設置了removeAbandoned="true",連接就可以自動回收。
連接自動回收判斷標准:
<!--是否回收已經超過 removeAbandonedTimeout 設置的無效連接,自動回收超時連接 啟動機制:getNumActive() > getMaxActive() - 3 和 getNumIdle() < 2 假設maxActive=20,而當前18個活動連接,1個空閑連接,機制將會啟動 但是只有在活動連接沒有使用的時長超過“removeAbandonedTimeout”(默認300秒)上述配置為60s,的連接將被回收-->
配置logAbandoned="true",會在回收連接時打印日志。removeAbandoned是連接池的高級功能,生產環境上應當慎重配置。
因為有時應用程序執行長事務,在這種情況下,極有可能連接會被連接池誤回收。
該配置一般在uat使用,為了定位連接泄漏的位置而去使用。生產環境中連接的關閉應該靠程序自己保證。
問題一產生原因:如上述所說,直接對號入座
解決:1.適當增大 removeAbandonedTimeout時間,讓單次獲取的連接能夠執行時間更長一點,讓其支持更長一點的事務。
問題二產生原因:需要拐個彎,因為spring中配置事務時配置的service開啟一個事務,在service中拿到連接開啟一個事務,而遍歷中一直使用注入的dao去調用方法,
其本質就是一直使用一個連接,不會遍歷一次執行完重新獲取連接,導致該連接超時被tomcat關閉回收。
解決2:將所有dao層方法抽出來另放一個業務service層,注入dao層,方法里使用dao的調用方法。在原來的service層中注入業務service,原有dao調用的方法,全部替換成業務service調用的方法。
這樣每次業務service調用到(update、insert、delete)方法,就開啟一個事務,執行完就回收。再執行就有獲取一個連接,執行到事務方法后,又會主動關閉,
就不會因連接超時被tomcat強行回收了!