不斷優化配置,逐步提高效能——我的一次效能測試經歷

beifengwang發表於2014-06-09

近日,合作伙伴想要針對我們的應用伺服器做一個效能測試,測試的基礎是夥伴原有的一個功能龐大而結構複雜的業務系統,目的是看應用伺服器是否能夠滿足業務系統的需要,並對應用伺服器做一個總體評價。由於硬體資源有限,硬體伺服器的配置為:2顆四核的志強E5520,8G記憶體,250G硬碟,一臺普通PC Server,作業系統使用的是Windows Server 2003 SP2.

在測試初期,客戶端併發在100的時候,跑上不到1小時,伺服器基本就沒有反應了,此時檢視應用伺服器的JVM堆,都已經滿滿的了,而且非常平穩(幾乎沒有垃圾收集),貌似是客戶端100併發的時候,記憶體都已經用盡了。但是記憶體一直得不到釋放,想想看可能有這麼幾個原因:

應用系統內部存在記憶體洩漏,導致JVM不能及時執行垃圾回收,最終導致記憶體耗盡
應用系統在Session中放入太多的大物件資料,導致記憶體佔用過高
JVM引數設定不恰當,導致JVM不能及時垃圾回收(這條是在本次測試過程中總結出來的,這也是平時最容易碰到的問題,想想之前開發時碰到的一些問題,也許跟這個關係巨大)
應用伺服器存在bug
分析一下,客戶描述應用是一個省級的業務系統,生產環境下最大併發數能達到1000左右,執行時也沒有問題,而且業務系統已穩定執行很長時間,看樣子1、2兩條可能性不高。同時,檢視此時的伺服器資源佔用情況,發現CPU(2顆4核超執行緒的CPU)使用率極低,一直在3%-7%之間,而其中有一個核,利用率一直在90%以上,甚至經常達到100%,而其他核心非常閒,沒有任何運算在執行。此時,也沒有使用過任何Java監控及管理工具,一時陷入困惑中。無意間翻看之前的一些針對應用伺服器的測試報告,發現幾乎所有的測試,都對Java執行的引數做了大量改動,尤其是指定了很多關於Java虛擬機器的執行控制引數,在大體瞭解幾個引數的功能以及具體的伺服器情況之後,決定不妨一試。於是在Java的啟動引數中加上了一些關於JVM堆疊及垃圾收集的一些引數,經過幾次調整,最終使用了引數:“-XX:NewSize=500m -XX:MaxNewSize=500m -XX:NewRatio=2 -XX:SurvivorRatio=8 -XX:+UseParallelGC -XX:ParallelGCThreads=8”(關於這些引數的意義,將在以後的文章中逐漸補充,或者可以搜一下),在此次引數改動之後,系統的8個核心,在閒(沒有接收大併發)的時候一直處於10%左右的使用率的情況,估計這些核心在一直不停的進行垃圾收集,而此後,再也沒有出現之前發生的記憶體一直被佔用,系統沒有反應的情況。甚至併發達到300時,系統執行效率仍然很高。至此,總結出一條結論:所有的Java系統都是執行在JVM之上,JVM的效能直接影響整個系統的效能,好的JVM是好Java應用系統的基礎。當你的Java應用出現效能瓶頸的時候,首先考慮優化JVM啟動引數。

另外,據說為保證系統在效能測試時的效率,防止JVM進行FullGC,可以將JVM的FullGC關閉,即在啟動引數中加上“-XX:+DisableExplicitGC”。

在效能測試中出現的另外一個情況是:系統反應慢,但是應用伺服器所在的伺服器資源佔用率很低,緩慢的反應速度使測試再次陷入僵局。此時,仍然是一個意外,解開了謎題。使用應用伺服器內建的資料庫連線池監控工具,發現資料庫連線池中存在大量等待的執行緒,最多時甚至到了將近200個,難道是資料庫連線池不夠大?於是放大連線池的容量一倍,最大連線數達到300個。在重啟資料來源之後,系統效能立馬提升,瓶頸消失了。

由此看來,影響Java應用的效能的最常見的2個問題就是:JVM的效率以及資料庫連線池。配置一個最合適的JVM就成功了一半,再加上一個合適的資料庫連線池(當然也可以使用Spring等管理連線池甚至自己編寫相關的資料庫連線管理工具),剩下的就只有開發一個優異的應用系統了。

另外,一個好的管理監控工具也可以成為提高效能的輔助手段。JDK5.0以上的jconsole工具,已經非常直觀的將JVM記憶體及執行緒資訊顯示出來了,基本上可以滿足一般系統的需要。IBM、Oracle的Java虛擬機器也提供了很多效能監控管理工具。這裡再加一句,如果應用系統在執行時出現效能問題,或者出現類似記憶體一直佔滿,CPU比較閒的情況,可以使用JConsole提供的手動GC按鈕,強制執行一次GC,再檢視記憶體情況,也許這時候問題就迎刃而解了。

最後,還是要闡述一下,沒有最好只有最均衡,這是原來做開發的感悟,現在看來是整個軟體領域的公理。由於此次針對壓力測試,會進行一些效能優先的引數配置,而實際測試過程中,由於網路或其他原因,總是導致資料庫連線失效,在重新啟用閒置資料庫時,未進行連線有效性檢查,最終導致系統全部無法獲取資料庫連線,並進入一個永遠使用無效資料庫連線的“死迴圈”裡面。此時,綜合考慮穩定性與效能,最終決定放棄一部分效能,來保證穩定性,最終,應用伺服器取得了一個較好的效能與穩定性,得到客戶贊同。

更多詳情

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29212814/viewspace-1178527/,如需轉載,請註明出處,否則將追究法律責任。

相關文章