日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

原文地址:https://mp.weixin.qq.com/s/fP--JJnkTR92NWdZtdEgqQ

作者:阿飛的博客

 

一些長時間GC停頓問題的排查及解決辦法

 

對于許多企業級應用,尤其是OLTP應用來說,長暫停很可能導致服務超時,而對這些運行在JVM上的應用來說,垃圾回收(GC)可能是長暫停最主要的原因。本文將描述一些可能碰到GC長暫停的不同場景,以及說明我們如何排查和解決這些GC停頓的問題。

下面是一些應用在運行時,可能導致GC長暫停的不同場景。

 

1. 碎片化

這個絕對要排在第一位。因為,正是因為碎片化問題--CMS最致命的缺陷,導致這個統治了OLAP系統十多年的垃圾回收器直接退出歷史舞臺(CMS已經是deprecated,未來版本會被移除,請珍惜那些配置了CMS的JVM吧),面對G1以及最新的ZGC,天生殘(碎)缺(片)的CMS毫無還手之力。

對于CMS,由于老年代的碎片化問題,在YGC時可能碰到晉升失敗(promotion failures,即使老年代還有足夠多有效的空間,但是仍然可能導致分配失敗,因為沒有足夠連續的空間),從而觸發Concurrent Mode Failure,發生會完全STW的FullGC。FullGC相比CMS這種并發模式的GC需要更長的停頓時間才能完成垃圾回收工作,這絕對是JAVA應用最大的災難之一。

為什么CMS場景下會有碎片化問題?由于CMS在老年代回收時,采用的是標記清理(Mark-Sweep)算法,它在垃圾回收時并不會壓縮堆,日積月累,導致老年代的碎片化問題會越來越嚴重,直到發生單線程的Mark-Sweep-Compact GC,即FullGC,會完全STW。如果堆比較大的話,STW的時間可能需要好幾秒,甚至十多秒,幾十秒都有可能。

接下來的cms gc日志,由于碎片率非常高,從而導致promotion failure,然后發生concurrent mode failure,觸發的FullGC總計花了17.1365396秒才完成:

一些長時間GC停頓問題的排查及解決辦法

 

 

一些長時間GC停頓問題的排查及解決辦法

 

 

一些長時間GC停頓問題的排查及解決辦法

 

2. GC時操作系統的活動

當發生GC時,一些操作系統的活動,比如swap,可能導致GC停頓時間更長,這些停頓可能是幾秒,甚至幾十秒級別。

如果你的系統配置了允許使用swap空間,操作系統可能把JVM進程的非活動內存頁移到swap空間,從而釋放內存給當前活動進程(可能是操作系統上其他進程,取決于系統調度)。SwApping由于需要訪問磁盤,所以相比物理內存,它的速度的令人發指。所以,如果在GC的時候,系統正好需要執行Swapping,那么GC停頓的時間一定會非常非常非常恐怖。

下面是一段持續了29.48秒的YGC日志:

一些長時間GC停頓問題的排查及解決辦法

 

最后一行[Times: user=915.56, sys=6.35, real=29.48 secs]中real就是YGC時應用真實的停頓時間。

發生YGC的這個時間點,vmstat命令輸出結果如下:

一些長時間GC停頓問題的排查及解決辦法

 

YGC總計花了29秒才完成。vmstat命令輸出結果表示,可用swap空間在這個時間段減少了600m。這就意味著,在GC的時候,內存中的一些頁被移到了swap空間,這個內存頁不一定屬于JVM進程,可能是其他操作系統上的其他進程。

從上面可以看出,操作系統上可用物理內容不足以運行系統上所有的進程,解決辦法就是盡可能運行更少的進程,增加RAM從而提升系統的物理內存。在這個例子中,Old區有9G,但是只使用了1.8G(mark-sweep generation total 9437184K, used 1860619K)。我們可以適當的降低Old區的大小以及整個堆的大小,從而減少內存壓力,最小化系統上的應用發生swapping的可能。

除了swapping以外,我們也需要監控了解長GC暫停時的任何IO或者網絡活動情況等, 可以通過IOStat和netstat兩個工具來實現. 我們還能通過mpstat查看CPU統計信息,從而弄清楚在GC的時候是否有足夠的CPU資源。

3. 堆空間不夠

如果應用程序需要的內存比我們執行的Xmx還要大,也會導致頻繁的垃圾回收,甚至OOM。由于堆空間不足,對象分配失敗,JVM就需要調用GC嘗試回收已經分配的空間,但是GC并不能釋放更多的空間,從而又回導致GC,進入惡性循環。

應用運行時,頻繁的FullGC會引起長時間停頓,在下面這個例子中,Perm空間幾乎是滿的,并且在Perm區嘗試分配內存也都失敗了,從而觸發FullGC:

一些長時間GC停頓問題的排查及解決辦法

 

同樣的,如果在老年代的空間不夠的話,也會導致頻繁FullGC,這類問題比較好辦,給足老年代和永久代,不要做太摳門的人了,嘿嘿。

4. JVM Bug

什么軟件都有BUG,JVM也不例外。有時候,GC的長時間停頓就有可能是BUG引起的。例如,下面列舉的這些JVM的BUG,就可能導致Java應用在GC時長時間停頓。

一些長時間GC停頓問題的排查及解決辦法

 

如果你的JDK正好是上面這些版本,強烈建議升級到更新BUG已經修復的版本。

5. 顯示System.gc調用

檢查是否有顯示的System.gc調用,應用中的一些類里,或者第三方模塊中調用System.gc調用從而觸發STW的FullGC,也可能會引起非常長時間的停頓。如下GC日志所示,Full GC后面的(System)表示它是由調用System.GC觸發的FullGC,并且耗時5.75秒:

一些長時間GC停頓問題的排查及解決辦法

 

如果你使用了RMI,能觀察到固定時間間隔的FullGC,也是由于RMI的實現調用了System.gc。這個時間間隔可以通過系統屬性配置:

一些長時間GC停頓問題的排查及解決辦法

 

JDK 1.4.2和5.0的默認值是60000毫秒,即1分鐘;JDK6以及以后的版本,默認值是3600000毫秒,即1個小時。

如果你要關閉通過調用System.gc()觸發FullGC,配置JVM參數 -XX:+DisableExplicitGC即可。

那么如何定位并解決這類問題問題呢?

  1. 配置JVM參數:-XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps and -XX:+PrintGCApplicationStoppedTime. 如果是CMS,還需要添加-XX:PrintFLSStatistics=2,然后收集GC日志。因為GC日志能告訴我們GC頻率,是否長時間停頓等重要信息。
  2. 使用vmstat, iostat, netstat和mpstat等工具監控系統全方位健康狀況。
  3. 使用GCHisto工具可視化分析GC日志,弄明白消耗了很長時間的GC,以及這些GC的出現是否有一定的規律。
  4. 嘗試從GC日志中能否找出一下JVM堆碎片化的表征。
  5. 監控指定應用的堆大小是否足夠。
  6. 檢查你運行的JVM版本,是否有與長時間停頓相關的BUG,然后升級到修復問題的最新JDK。

分享到:
標簽:停頓 GC
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定