簡析關於定時任務跑著跑著就停止了的問題
前兩天專案中遇到個問題,用定時任務每隔30秒去下載圖片到本地,定時任務跑十幾次之後就停止了。
用的是 spring內部自帶的task任務排程, 一般來說定時任務突然停止有以下幾方面的原因:
一是定時任務的配置問題,只配了多久發生一次和發生時執行的方法,所以這個原因排除。
二是資料庫連線超時,因為連線超時會有異常提示資訊,並沒有這個原因也排除了。
三是執行緒死鎖或阻塞,當時覺得就是這個原因了,然後關掉了其他的定時任務,然後看了下執行緒列表,發現執行緒
死鎖導致阻塞也是不可能的。
最後實在是沒辦法了,把定時任務的方法,和它呼叫的方法的每個分支都加了日誌打印出來,發現每次跪的地都是
從sqlserver資料庫裡取資料的時候 ,由於日誌較多看了好久,分析了幾次才發現這個問題。比較尷尬,查了資料
發現
因為hibernate是有自己的連線池在使用的時候我們新建的所有連線都會存在這個連線池中,如果建的新連線
太多而不釋放,那麼就會導致新連線無法建立,從而阻塞,這也就是定時任務跑著跑著突然停止的原因。
這就需要在hibernate的配置中增加連線釋放模式:hibernate.connection.release_mode
記憶裡從來沒有配置過這個東西,如果不配置,預設是on_close,
這個配置項有三個選擇:after_statement/after_transaction/on_close,javadoc中可以看出它們的用處,
那麼如果沒有顯示的去呼叫session.close或其它關閉連線的方法的話,這個連線時不會被關閉
的!在用到連線池的時候,就更會出現問題了,池中的連線會一直存在著而不會被關閉和回收!
具體的配置:<property name="hibernate.connection.release_mode">after_transaction</property>
放在你的hibernate配置裡面就可以了。這樣我們的連線自動釋放後就不會出現上述問題了。
網上還找到了一個原因說是tomcat自動清理或超時,因為問題解決了就沒有去嘗試。百度了下說是涉及到真死和
假死,要去抓個dump分析,希望之後有機會去嘗試。