天天看點

CPU占用高

前天下午,伺服器突然沒響應,日志出現記憶體溢出異常,最後确認CPU占用過高導緻出現問題,使用jvisualvm來監控jvm,也無法連接配接上伺服器,業務高峰期情況下,隻能先啟用備用伺服器,以便檢查,結果備用伺服器沒撐過10分鐘,也出現同樣現象,實際線上使用者不多,按理并發量也不大,而且以前這個量也承受過來,在沒辦法情況下,隻能再次啟用多台備用伺服器,然後一個人監控,負責kill,restart。留一台給我們做分析(在測試環境壓測,無法重制改現象),jvisualvm監視視圖,gc占用CPU并不高(感覺這個不準确),但整個堆記憶體将近封頂,之後隻能嘗試逐漸加上列印gc日志(-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/\heapdump.hprof -Xloggc:/tmp/gc.log -XX:+PrintGCDetails),并且利用jstack列印線程棧資訊(見:http://lippeng.iteye.com/blog/2001254)

CPU占用高

 隻後檢視gc日志和jstackfile檔案,從gc日志發現,都在做full gc,每次gc後,新生代釋放一點點記憶體,年老代沒變,這樣看來的确有東西一直在做死循環運算,并不斷産生出對象,然後到達full gc臨界值,觸發full gc,釋放的空間又馬上被新産生的對象塞滿;

CPU占用高

從jstackfile檔案,依照定位查找占用CPU高的線程

CPU占用高

 檢查代碼,的确發現遞歸算法,最後确認資料存在問題,導緻根據樹型資料,擷取所有下級節點出現死循環(有個節點,上級節點是其自身導緻)。

因樹形資料,是第三方準備,真TMD坑爹。

自己後來本地模拟改現象,發現jvisualvm監視視圖對于CPU占用,還是蠻準确的,不知道為什麼當時生産不準确:

CPU占用高

如何定位程序中哪個線程占用CPU高,參見:http://www.iteye.com/topic/1132321

參考:

https://gist.github.com/rednaxelafx/1081908#file_notes.md

一篇JVM監控&調優參數好文:http://www.cnblogs.com/zhguang/p/3342039.html,摘選:

調優方法

一切都是為了這一步,調優,在調優之前,我們需要記住下面的原則:

  1. 多數的Java應用不需要在伺服器上進行GC優化;
  2. 多數導緻GC問題的Java應用,都不是因為我們參數設定錯誤,而是代碼問題;
  3. 在應用上線之前,先考慮将機器的JVM參數設定到最優(最适合);
  4. 減少建立對象的數量;
  5. 減少使用全局變量和大對象;
  6. GC優化是到最後不得已才采用的手段;
  7. 在實際使用中,分析GC情況優化代碼比優化GC參數要多得多;

GC優化的目的有兩個(http://www.360doc.com/content/13/0305/10/15643_269388816.shtml):

  • 将轉移到老年代的對象數量降低到最小;
  • 減少full GC的執行時間;

為了達到上面的目的,一般地,你需要做的事情有:

  • 減少使用全局變量和大對象;
  • 調整新生代的大小到最合适;
  • 設定老年代的大小為最合适;
  • 選擇合适的GC收集器;

在上面的4條方法中,用了幾個“合适”,那究竟什麼才算合适,一般的,請參考上面“收集器搭配”和“啟動記憶體配置設定”兩節中的建議。但這些建議不是萬能的,需要根據您的機器和應用情況進行發展和變化,實際操作中,可以将兩台機器分别設定成不同的GC參數,并且進行對比,選用那些确實提高了性能或減少了GC時間的參數。

真正熟練的使用GC調優,是建立在多次進行GC監控和調優的實戰經驗上的,進行監控和調優的一般步驟為:

1,監控GC的狀态

使用各種JVM工具,檢視目前日志,分析目前JVM參數設定,并且分析目前堆記憶體快照和gc日志,根據實際的各區域記憶體劃分和GC執行時間,覺得是否進行優化;

2,分析結果,判斷是否需要優化

如果各項參數設定合理,系統沒有逾時日志出現,GC頻率不高,GC耗時不高,那麼沒有必要進行GC優化;如果GC時間超過1-3秒,或者頻繁GC,則必須優化;

注:如果滿足下面的名額,則一般不需要進行GC:

  • Minor GC執行時間不到50ms;
  • Minor GC執行不頻繁,約10秒一次;
  • Full GC執行時間不到1s;
  • Full GC執行頻率不算頻繁,不低于10分鐘1次;

3,調整GC類型和記憶體配置設定

如果記憶體配置設定過大或過小,或者采用的GC收集器比較慢,則應該優先調整這些參數,并且先找1台或幾台機器進行beta,然後比較優化過的機器和沒有優化的機器的性能對比,并有針對性的做出最後選擇;

4,不斷的分析和調整

通過不斷的試驗和試錯,分析并找到最合适的參數

5,全面應用參數

如果找到了最合适的參數,則将這些參數應用到所有伺服器,并進行後續跟蹤。