2015-02-24 48 views
2

我們在AWS上的Tomcat上運行基於Jersey(1.x)的服務,其中包含約20個實例數組週期性實例「變差」:在大約4小時的過程中,其堆和CPU使用量會增加,直到堆耗盡並且CPU被鎖定。此時它會自動從負載平衡器中移除並最終死亡。未完成的耗盡內存的對象

從這些實例中檢查堆轉儲,大約95%的內存已被一個java.lang.ref.Finalizer實例佔用,該實例持有各種各樣的東西,但其大部分或全部與HTTPS連接sun.net.www.protocol.https.HttpsURLConnectionImpl,sun.security.ssl.SSLSocketImpl,各種加密對象)。這些是我們使用Jersey的客戶端庫進行外部Web服務的連接。來自「健康」實例的堆轉儲並不表示任何問題。

在相對較低的負載情況下運行幾天或幾周沒有問題。隨着負載的增加,實例故障的頻率也會增加(平均CPU達到〜40%時每天幾個)。

我們的JVM ARG遊戲:

-XX:+UseG1GC -XX:MaxPermSize=256m -Xmx1024m -Xms1024m 

我在加入JMX日誌記錄垃圾收集量度的過程,但我不完全清楚我應該尋找。在這一點上,我主要是在尋找什麼能夠啓動這種失敗或追加調查目標的想法。

+0

可能是相關的:http://stackoverflow.com/questions/8355064/is-memory-leak-why-java-lang-ref-finalizer-eat-so-much-memory – aruisdante 2015-02-24 17:42:37

回答

0

這最終證明是由JVM錯誤引起的(不幸的是我失去了鏈接到我們追蹤到的特定鏈接)。升級到更新版本的OpenJDK(我們以OpenJDK 1.7.0_50結束)解決了這個問題,但我們沒有對代碼進行任何更改。

0

它可能是一個連接泄漏?我假設你已經檢查了嗎?

我有類似的問題與GC臭蟲。取決於您的JVM版本,看起來您正在使用實驗性(並且可能有錯誤)功能。您可以嘗試禁用G1並使用默認垃圾回收器。同樣取決於你的版本,你可能會遇到一個垃圾回收的開銷,因爲它需要很長的時間來計算什麼可以和不能被垃圾回收。 -XX:-UseGCOverheadLimit可能會對你的JVM有幫助。

+0

這不是明顯的連接泄漏。健康情況堆積如山,沒有顯示出任何額外連接的跡象;這實際上只是不健康實例中的終結者隊列。我們使用Java 7(OpenJDK 1.7.0_25),因此G1得到官方支持,但我實際上並不知道是什麼讓我們選擇了那個。我們正在運行的其他服務似乎只是使用默認的Parallel GC而沒有問題。 – 2015-02-24 18:02:30

0

Java使用單個終結器線程來清理死掉的對象。您機器的症狀與積壓的終結處理堆積如山。如果終結器線程速度太慢(因爲某個對象需要很長時間才能完成),則終結器隊列條目的結果累積可能導致終結器線程落在進入的對象後面,直到所有事件停止。

您可能會發現在確定哪些對象正在減慢終結器線程時有助於分析。

+0

這聽起來像是在這裏發生的事情,我只需要弄清楚什麼是設置的東西。到目前爲止,我還沒有取得很多成功,因爲我無法在生產環境之外複製故障狀態。即使在重負的情況下,當我看到一個健康的實例時,沒有什麼看起來與衆不同。 – 2015-02-24 18:07:58