JRun執行緒池配置
在過去 6 個月的大部分時間裡,我和我的團隊一直在努力保持集群 ColdFusion 應用程序的穩定,但收效甚微。我們轉向 SF,希望能找到一些 JRun 專家或新想法,因為我們似乎無法弄清楚。
設置:
兩個 ColdFusion 7.0.2 實例在 Windows Server 2003 下的 IIS 6 上使用 JRun 4(帶有最新更新)集群。兩個四核 CPU,8GB RAM。
問題:
不時地,通常每週一次,其中一個實例將完全停止處理請求。它沒有任何活動,我們必須重新啟動它。
我們所知道的:
每次發生這種情況時,JRun 的錯誤日誌總是充滿 java.lang.OutOfMemoryError: unable to create new native thread。
在閱讀了來自 Macromedia/Adobe 的 JRun 文件和許多令人困惑的部落格文章之後,我們或多或少地將其縮小到實例的 jrun.xml 中不正確/未優化的 JRun 執行緒池設置。
我們 jrun.xml 的相關部分:
<service class="jrun.servlet.jrpp.JRunProxyService" name="ProxyService"> <attribute name="activeHandlerThreads">500</attribute> <attribute name="backlog">500</attribute> <attribute name="deactivated">false</attribute> <attribute name="interface">*</attribute> <attribute name="maxHandlerThreads">1000</attribute> <attribute name="minHandlerThreads">1</attribute> <attribute name="port">51003</attribute> <attribute name="threadWaitTimeout">300</attribute> <attribute name="timeout">300</attribute> {snip} </service>
上週我啟用了 JRun 的指標記錄來收集與執行緒相關的數據。這是記錄一周後的數據摘要。
平均值:
{jrpp.listenTh} 1 {jrpp.idleTh} 9 {jrpp.delayTh} 0 {jrpp.busyTh} 0 {jrpp.totalTh} 10 {jrpp.delayRq} 0 {jrpp.droppedRq} 0 {jrpp.handledRq} 4 {jrpp.handledMs} 6036 {jrpp.delayMs} 0 {freeMemory} 48667 {totalMemory} 403598 {sessions} 737 {sessionsInMem} 737
最大值:
{jrpp.listenTh} 10 {jrpp.idleTh} 94 {jrpp.delayTh} 1 {jrpp.busyTh} 39 {jrpp.totalTh} 100 {jrpp.delayRq} 0 {jrpp.droppedRq} 0 {jrpp.handledRq} 87 {jrpp.handledMs} 508845 {jrpp.delayMs} 0 {freeMemory} 169313 {totalMemory} 578432 {sessions} 2297 {sessionsInMem} 2297
關於我們現在可以嘗試什麼的任何想法?
乾杯!
編輯 #1 -> 我忘了提及的事情:Windows Server 2003 Enterprise w/JVM 1.4.2(用於 JRun)
最大堆大小約為 1.4GB 是的。我們曾經有洩漏,但我們修復了它們,現在應用程序使用大約 400MB,很少更多。最大堆大小設置為 1200MB,所以我們沒有達到它。當我們確實有洩漏時,JVM 就會爆炸,實例會自行重啟。現在沒有發生這種情況,它只是停止處理傳入的請求。
我們認為這與這篇博文之後的執行緒有關: http ://www.talkingtree.com/blog/index.cfm/2005/3/11/NewNativeThread
拋出的 Java 異常是 OutOfMemory 類型,但實際上並不是說我們用完了堆空間,只是說它無法創建新執行緒。異常類型有點誤導。
基本上,部落格是說 500 作為 activeHandlerThreads 可能太高了,但我的指標似乎表明我們沒有接近讓我們感到困惑的地方。
好吧,在進入 JRun 配置細節之前,讓我們先看看一些更大的問題。
如果您在 JRun 錯誤日誌中收到 java.lang.OutOfMemoryError 異常,那麼您的記憶體不足。請不要對此表示贊同;-)。您沒有說您執行的是 32 位還是 64 位 Windows,但您確實說您有 8 GB 的 RAM,因此這會對答案產生一些影響。無論您執行的是 32 位還是 64 位 JVM(以及什麼版本)也會影響事情。所以這些是一些答案,可以幫助我們深入了解這一點。
無論如何,您的應用程序記憶體不足。由於以下一個或多個原因,它的記憶體不足:
- 您的應用程序正在洩漏記憶體。您的應用程序使用的某些對象會被持續引用,因此永遠不符合垃圾收集的條件;或者更糟 - 在每個請求上創建的一些新對像被另一個對象永久引用,因此永遠沒有資格進行垃圾收集。在這方面,正確的 J2EE 會話處理可能特別棘手。
- 處理每個並發請求(在配置的並發請求級別)所需的記憶體量超過了 JVM 堆中可用的記憶體量。例如,您有一個 1 GB 的堆大小,每個請求最多可以使用 10 MB。您的應用伺服器已調整為允許 150 個並發請求。(簡單的數字,我知道)。在這種情況下,如果您在負載下遇到 100 個或更多並發請求(如果每個請求都使用了完成請求所需的最大記憶體量),那麼您肯定會耗盡記憶體。
其他要記住的事情:在 32 位 Windows 上,32 位 JVM 只能分配大約 1.4 GB 的記憶體。如果 64 位 Windows 上的 32 位 JVM 的限制小於任何 32 位程序的理論最大 4 GB,我不記得了。
更新
我閱讀了通過 TalkingTree 連結的部落格文章以及該文章中連結的另一篇文章。我沒有遇到這種確切的情況,但我確實有以下觀察結果:JRUN 指標日誌記錄可能不會記錄您線上程使用高峰期引用的“最大值”。我認為它以固定的重複間隔記錄指標。這有助於向您展示應用程序的平穩、平均性能特徵,但它可能無法在錯誤情況開始發生之前擷取 JRUN 的狀態。
在不了解 JRUN 執行緒管理的內部工作原理的情況下,我仍然說它確實記憶體不足。也許它不是記憶體不足,因為您的應用程序需要在 JVM 堆上分配記憶體並且沒有可用的記憶體,但它記憶體不足,因為 JRUN 試圖創建另一個執行緒來處理傳入請求,而支持另一個執行緒所需的堆記憶體是’ t 可用——換句話說,執行緒不是空閒的——它們也需要堆記憶體。
您的選擇似乎如下:
- 減少您的應用程序在每個請求中使用的記憶體量,或者 -
- 實驗性地降低 JRUN 配置中執行緒調整參數的值,以使更多執行緒排隊等待處理,而不是同時變為可執行,或者 -
- 在 ColdFusion 管理員中減少同時請求的數量(請求調整頁面,欄位“同時模板請求的最大數量”)
無論您追求哪種選擇,我認為這裡的有效解決方案本質上都是實驗性的。你將不得不做出改變,看看它對應用程序有什麼影響。你有一個負載測試環境,對吧?