处理缓慢的资源泄漏
使用Java監視器查找資源泄漏
查找緩慢的資源泄漏是使應用程序服務器長時間保持正常運行的關鍵。 在這里,我解釋了如何使用Java監視器來發現緩慢的資源泄漏,以及如何驗證它們是實際的泄漏,而不僅僅是額外的預分配到某些HTTP連接器或數據庫池中。 如果執行這些步驟,則可以擺脫定期重新啟動,并真正開始依賴服務器。
緩慢的資源泄漏是一個問題,因為它們迫使您定期重新啟動應用程序服務器。 反過來,這意味著您始終必須密切注意服務器,因為它們隨時可能崩潰。 最終,您不能依賴遭受緩慢資源泄漏的服務器。 跟蹤和解決緩慢的資源泄漏需要時間和耐心。 一旦完成幾次,這并不是很難做到的。
您還需要一個監視工具,該工具可以顯示過去幾周甚至幾個月內來自服務器的統計信息。 如果在服務器上啟用了更長的數據存儲,則可以使用Java監視器來執行此操作。 要在Java監視器中啟用此功能,請首先開始對服務器使用Java監視器 。 在帶有服務器圖形的頁面上,可以通過切換到“ 1周”或“ 1個月”視圖來啟用更長的數據,如下所示。
第一步是查看過去一周中服務器的數據。 為了發現資源泄漏,我發現繪制一周的數據比查看Java監視器標準的兩天的數據要好。 峰平滑了,這些圖讓我看看例如內存使用隨時間如何發展。
為了預測即將發生的中斷和緩慢的資源泄漏,我尋找兩種模式。 首先要檢查的模式是,資源使用量不會隨時間增加,而會隨著每日流量的增加和減少而增加和減少。 當一天的流量減少后,我預計資源使用量將回落到名義水平。 我檢查資源使用率是否每次都回落到同一水平。
請注意,我故意使用模糊的術語,例如“資源”。 在實踐中,我查看所有內存,文件描述符以及HTTP連接器和數據庫連接池的圖形。 所有這些都是緩慢的資源泄漏的候選者。
當我看到資源似乎在增長的時候,我切換到數據的每月視圖,甚至年度視圖。 這將壓縮圖中的數據,并使緩慢的資源泄漏更容易發現。
這是資源使用情況可疑更改的示例。 在這種情況下,系統上的垃圾收集器突然變得更加活躍。 此時,系統或系統負載沒有變化。
我要注意的第二種模式是服務器重啟重啟后資源分配急劇下降。 重新啟動應用程序服務器時,如果資源使用量顯著下降,則可能表明資源泄漏緩慢。 重新啟動之后,通常會像重新啟動之前那樣降低資源使用量,因為所有池和緩存都開始為空。
這是一個與重啟相關的資源使用變化的示例,該變化并不表示有問題。 重新啟動后一段時間(甚至幾天),資源使用情況已更改,但隨后又恢復到正常水平并停留在該水平。
這是另一個。 甚至更加可疑,因為重新啟動后資源使用率并未恢復。 它只是掉下來并停留下來。 這幾乎肯定是一個問題。
一旦確定資源使用模式可疑,就必須確認這實際上是一個緩慢的泄漏。 很有可能是緩存或池中填充了更多緩存,從而隨著時間的推移提高了資源使用率,而沒有實際的泄漏。 在這一步中,我將遍歷線程和數據庫池的圖以及HTTP會話的圖。 我試圖從那里的圖表來解釋提高的資源使用情況。
例如,在這里我們看到JVM中活動的線程,但線程數量有些奇怪的下降。 這些下降表明系統重新啟動。
但是,如果將該圖與同一臺服務器上的HTTP連接器池圖進行比較,我會發現HTTP連接器池中預分配的線程數同樣會上下波動。
這可能意味著沒有緩慢的資源泄漏。 最有可能的是,池中的額外線程保持狀態,從而導致其他資源也增加。 我可能會記下具體注意此服務器的信息,但我還沒有開始深入研究資源泄漏。
只有當我無法解釋池中分配的額外資源和活動HTTP會話的數量時,我才真正開始挖掘。 如下所述: 如何找到資源泄漏緩慢的根本原因 。
解決緩慢的資源泄漏
我們研究了如何較早發現緩慢的內存泄漏。 在那里,我們看到了如何找到緩慢的資源泄漏,以及如何將其與預期的池增長行為區分開。
在這里,我想解釋一下如何確定緩慢的資源泄漏的根本原因,以及最終如何解決它們。 修復緩慢的資源泄漏幾乎總是需要更改代碼,因此,如果您無法更改代碼,則無法修復緩慢的資源泄漏。 在這種情況下,您將必須找到可以的人。
確定緩慢的資源泄漏的根本原因的過程類似于發現快速泄漏的過程。 主要的區別是時間對您不利。 對于快速泄漏,您可以輕松地進行幾次迭代,而緩慢的泄漏則可能需要數周或數月的時間才能顯現出來。 迭代可能是一年的四分之一。 為了加快泄漏速度,您可以快速更改代碼并“實時查看其運行狀況”。 對于較慢的泄漏,這僅意味著您將永遠找不到真正的問題。
要遵循的步驟是:
請注意,我們通常通常只快速地執行步驟3,然后將所有精力花在步驟5上,卻發現真正的問題是其他問題。 我應該知道,因為我犯錯的次數比我愿意承認的還要多。
一旦知道泄漏了哪些資源(例如內存,文件描述符,CPU周期,線程),便開始收集有關泄漏的證據。 該證據來自多個來源。 如果泄漏的資源僅在您的代碼中很少使用,則應用程序源代碼是開始收集的好地方。 如果這是在各處(例如內存)使用的東西,那么查看源代碼通常很耗時,并且效率不高。 因此,這是我要尋找證據的備忘單:
- 記憶
--->堆轉儲 - 文件描述符
---> Java監視器的線程池圖以及lsof或sockstat - 中央處理器
--->線程轉儲 - 線程數
---> Java監視器的線程池圖和線程轉儲 - 數據庫連接
--->在JDBC驅動程序上啟用資源泄漏檢測
收集證據時,保持開放的態度非常重要。 得出關于正在發生的事情的結論是非常誘人的。 相反,只需查看很酷的證據并消除可能的問題。
至關重要的一步是向不懼怕挑戰您的人提供您的證據和思路。 此步驟是為了防止您在分析中犯錯誤,并且必須等待幾周才能發現自己是錯誤的。 在這個階段,只是點頭和鼓掌的人可能弊大于利,不管這個人的意圖多么好。 找到合適的人,并告訴該人您需要嚴格的審查。
一旦分析克服了這一挑戰,您就可以最終開始考慮解決方案。 該解決方案需要包括兩個部分:1)它需要以使系統為您提供有關剛剛發現的問題的證據的方式來改進日志記錄和監視,以及2)它需要實際解決該問題。
如果您的解決方案不正確,改進的日志記錄將為您提供新的新證據,以供您進行第二次(可能是最終的!)迭代。
翻譯自: https://www.javacodegeeks.com/2013/09/dealing-with-slow-resource-leaks.html
總結
- 上一篇: 安全地创建和存储密码
- 下一篇: 支付宝建信养老飞越366怎么取出来?