記一次服務cpu爆高異常

image

這幾天進行架構整改,將業務服務話,然後單獨部署,但是有一臺服務的運行時,cpu特別高,基本都是90%以上,導致服務的消費能力特別差。這種級別bug,簡直是一種噩夢,但還是必須得解決。

發現問題:

1.服務部署到linux之後,通過top命令觀察服務的cpu和內存使用情況

image

我們可以很明顯的看到,在java進程中cpu使用率超級高,所以我們需要進一步的排查,是java進程中哪一個線程導致cpu如此高負載的。

2.通過如下命令,我們可以查看java進程是因爲哪一個線程引起的。

ps -mp 23615 -o THREAD,tid,time
printf "%x\n" 線程號
jstack 進程號|grep 16進制異常線程號 -A90

image

我們可以很明顯的看到,最耗費性能的是gc垃圾回收線程引起的,這說明jvm在垃圾回收可能很頻繁。

3.通過命令查看jvm垃圾回收情況

jstat -gc 2592 5000

image

通過命令,我們可以很明顯的看到YGC都沒發生,FGC一直在疊加,說明老年代回收頻率特別高,這也是cpu爆高的最終原因。

解決方案:

既然問題已經找到了,那我們應該如何解決呢?

從上面的問題可以得出應該是jvm參數配置有誤,導致頻繁的full gc,新生代回收基本沒用到,所以我們需要調整jvm的參數,讓full gc少發生,新生代得到充分使用,從而降低cpu佔用率。

下面是博主我針對上面的問題,調優而成的配置:

-Xmx3000M
最大堆內存
-Xms3000M
最小堆內存
-Xmn600M
年輕代大小
-XX:PermSize=500M
設置持久代(perm gen)初始值
-XX:MaxPermSize=500M
設置持久代最大值
-Xss256K
每個線程的堆棧大小
-XX:+DisableExplicitGC
關閉System.gc()
-XX:SurvivorRatio=1
Eden區與Survivor區的大小比值
-XX:+UseConcMarkSweepGC
使用CMS內存收集
-XX:+UseParNewGC
設置年輕代爲並行收集
-XX:+CMSParallelRemarkEnabled
降低標記停頓
-XX:+UseCMSCompactAtFullCollection
在FULL GC的時候, 對年老代的壓縮
-XX:CMSFullGCsBeforeCompaction=0
多少次後進行內存壓縮
-XX:+CMSClassUnloadingEnabled
垃圾回收會清理持久代,移除不再使用的classes
-XX:LargePageSizeInBytes=128M
內存頁的大小
-XX:+UseFastAccessorMethods
原始類型的快速優化
-XX:+UseCMSInitiatingOccupancyOnly
使用手動定義初始化定義開始CMS收集
-XX:CMSInitiatingOccupancyFraction=70
使用cms作爲垃圾回收,使用70%後開始CMS收集
-XX:SoftRefLRUPolicyMSPerMB=0
每兆堆空閒空間中SoftReference的存活時間
-XX:+PrintClassHistogram
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintHeapAtGC
-Xloggc:log/gc.log

應用上述的配置,服務的cpu和內存佔有率下降了一大截,穩定性也得到很大的提高,gc回收頻率大大降低了。

備註:

因爲上述截圖,是配置生效之後的數據,所以可能不準確。 參考地址:https://www.cnblogs.com/zexu-cheng/p/5079826.html

想學習分佈式、微服務、JVM、多線程、架構、java、python的童鞋,千萬不要掃碼,否則後果自負~

林老師帶你學編程https://wolzq.com

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章