2011-11-18 76 views
6

與任何內存管理問題一樣,這是一個漫長的故事,因此很難實現。混淆Tomcat持久會話內存配置文件

我們有一個應用程序,一直在遭受一些內存管理問題,所以我一直在試圖分析應用程序,以瞭解問題所在。我看到這個線程今天早些時候:

Tomcat Session Eviction to Avoid OutOfMemoryError

...這似乎跟風與我在探查看到。基本上,如果我用Jmeter與一羣用戶一起打開應用程序,它將會持續很長時間,直到會話開始過期。然而,與該線程中的海報不同,我擁有源代碼,並且可以選擇嘗試使用Tomcat實現持久狀態會話,而這正是我今天一直在嘗試做的事情,並取得了有限的成功。我認爲這是我缺少的一些配置設置。以下是我在context.xml中:

<Manager className='org.apache.catalina.session.PersistentManager' 
       saveOnRestart='false' 
       maxActiveSessions='5' 
       minIdelSwap='0' 
       maxIdleSwap='1' 
       maxInactiveInterval='600' 
       maxIdleBackup='0'> 
    <Store className='org.apache.catalina.session.FileStore'/> 
    </Manager> 

而且在web.xml我有這樣的:

<session-config> 
    <session-timeout> 
     10 
    </session-timeout> 
</session-config> 

理想我想在一個小時超時會議,但是出於測試目的,該很好。現在,在已經有一些東西打周圍,終於熬到這些設置,我看在探查的應用程序,這是我所看到的:

enter image description here

正如你可以在圖片中看到的,我有放一些註釋。這是圍繞問號圈起來的部分,我最不理解的就是其他問題。您可以看到我在幾個不同的點上使用Jconsole'執行GC'按鈕,並且您可以在圖表中看到我正在用Jmeter與許多客戶端進行應用程序碰撞的部分。

如果我記得正確(我必須回去並確實記錄它),在執行持久狀態之前,GC按鈕在清除堆時幾乎不會做太多。這裏的奇怪之處在於,似乎我必須手動運行GC來獲取此持久狀態,才能真正幫助解決任何問題。

另外,這只是一個普通的內存泄漏情況?今天早些時候,我收集了堆轉儲並將其加載到Eclipse Memory Analyzer工具中,並使用了「檢測泄漏」功能,它所做的只是強化了理論上這是會話大小問題;它檢測到的唯一泄漏是在java.util.concurrent.ConcurrentHashMap $ Segment,這導致我到這個線程Memory Fully utilized by Java ConcurrentHashMap (under Tomcat)

這讓我覺得它不是真正泄漏的應用程序。

其他相關細節: - 暫時在本地機器上運行/測試。這就是所有這些結果的來源。 - 使用Tomcat 6 - 這是一個應用程序JSF2.0 - 我已經添加了系統屬性-Dorg.apache.catalina.STRICT_SERVLET_COMPLIANCE =真按Tomcat文檔

所以,我想這裏存在幾個問題: 1.我有正確配置嗎? 2.是否有內存泄漏? 3.這個內存配置文件正在發生什麼? 4.它(相對)正常嗎?

在此先感謝。

UPDATE

所以,我想肖恩的提示,並發現了一些新的有趣的事情。

會話偵聽器工作得很好,並且在分析這種情況時起到了作用。還有一件事,我忘了提到的是,應用程序的負載只會被一個頁面混淆,而這個頁面在幾乎滑稽的比例上達到了功能複雜度。所以,在測試中,我有時會打到那個頁面,有時我會避免它。因此,在下一輪測試中,這次使用會話監聽器,我發現以下內容:

1)用幾十個客戶端訪問應用程序,只需訪問一個簡單的頁面。我注意到會議在指定的時間限制之後都按預期發佈,並且內存已經發布。對於複雜的情況,同樣的事情可以與少量的客戶端完美結合,打到'大'頁面。

2)接下來,我嘗試用複雜的用例與幾十個客戶端一起打開應用程序。這一次,啓動了數十次以上的會議。似乎每個客戶都是在一到三次會議之間發起的。會話到期時間結束後,會釋放一點內存,但根據會話偵聽器,只有大約三分之一的會話被銷燬。與此相反,實際包含會話數據的文件夾是空的。大部分使用的內存也被保存。但是,在運行壓力測試一小時後,垃圾收集器運行並且一切恢復正常。

所以,後續的問題包括:

1)爲什麼會會議進行適當的簡單的情況下進行處理,但是當事情變得內存密集型,他們不再被正確地管理?會話處理程序是否錯誤地報告了事情,還是使用JMeter以某種方式影響了它?

2)爲什麼垃圾收集器等待一個小時才能運行?是否有一個系統設置要求垃圾收集器必須在給定的時間範圍內運行,或者是否有一些我缺少的配置設置?

再次感謝您的支持。

更新2

只是一個快速注:與本多一些玩耍,我發現我得到有關活動會話的數量不同報告的原因是由於這樣的事實,我現在用的執着會議;如果我關閉它,一切都按預期工作。它的確在Tomcat頁面上說了持久會話,它是一個實驗性功能。它必須調用監聽器正在拾取的會話事件,當時人們會非常期望地這樣做。

回答

5

,讓我試着解決問題,我可以

  1. 對於您的配置,它看起來不錯,我在紙上的最好的。如果您想確保您的會話正在創建並正確銷燬,您需要設置一個會話偵聽器來記錄或顯示打開的會話列表。這裏是一個鏈接example

  2. 我不認爲有內存泄漏。增量GC正在運行。似乎有很多內存被提升到老一代。但是,一旦您的應用程序能夠運行完整的GC,內存將恢復正常。如果你需要你的用戶會話有大量的數據存儲在其中,內存將是你的權衡。只要您在註銷/超時後摧毀數據,從長遠來看內存應該沒問題。 您的問題(???)區域將是您的會話仍處於活動狀態的灰色區域,因此存儲在這些區域中的數據將被保留,可能會在此時被提升到舊版本。一旦內存升級到老一代,它需要一個完整的GC來清理它。點擊按鈕做到了。應用程序最終將安排完整的GC。

  3. 我覺得#2有助於回答這個

  4. 確保它看起來是正常的壓力測試。嘗試再次運行而不點擊執行GC按鈕。看看內存是否會自行回落。請注意,當垃圾收集器認爲它應該這樣做時,它將執行完整的GC。要清除舊的版本需要暫停,以便GC不會執行該操作,除非感覺它沒有足夠的資源來正確管理應用程序。

您可能想爲未來測試做的其他事情。注意年輕一代和堆老一代之間的堆使用情況。從截圖中我們可以看到有872mb的堆已提交,以便在加載測試期間分解內存所在的位置,這有助於正確識別堆保存的位置。

以類似的方式考慮打開verbose GC日誌記錄,以便您可以獲取堆分解的報告。有許多工具可以幫助您繪製GC日誌,因此您不必手動讀取日誌。如果你不想將它發送到標準輸出,這也可以記錄到一個文件(-Xloggc:file)。

如果會話大小變得太大而無法管理,您可能需要將該內存卸載到別處。一些例子可能是使用BigMemory,DB Persistance或其他減少會話大小的方法。

+0

肖恩,謝謝你的非常深入的解釋。對不起,我沒有早點回復你。我基本上發佈了並在週末下線了。無論如何,我接受了你的回答,但如果你有時間進一步幫助,我還會發布一些跟進問題。如果沒有,你的提示已經幫助我繼續前進,你的結論是沒有內存泄漏讓我放心。 – user470714

0

我沒有看到任何人都指出你的錯字:

minIdelSwap='0' 

不知道這是任何使用到任何人,但肯定會造成的PersistenceManager不同的行爲比你想象它。