一次線上 CPU 飆升問題的分析解決

前幾日,下了班在家時忽然收到監控報警,線上一組業務機器 CPU 被打滿至 100%,爲了保持服務的穩定運行,臨時採起了升級配置、加機器等粗暴的方法將當晚扛了過去。
半夜想了下可能的緣由,因爲可能因素太多,不能肯定,次日到公司後,在一臺預發機器上把 Java Mission Control 所需的參數配置好,而後就等待下一次問題出現唄,果真,沒幾天,在晚高峯時問題又復現了,立刻將線上的流量分了一小部分到提早配置好的預發機器上,沒過一會,預發機器的 負載 也滿了。在 Java Mission Control 的 Thread 的面板裏觀察了一會,業務線程的 CPU 使用率根本不高,超過 10% 的都不多,但此時 CPU 又是被打滿的,在不停查看 Java Mission Control 中提供的信息時,發現了 Full GC 很是頻繁,在應用啓動了兩個多小時內,Full GC 了 1500 屢次,佔用了 13 多分鐘,而且次數和時間依然在不停增長中,一下讓筆者想到了以前在相關書籍上提到的頻繁 Full GC 的相關問題,沒想到在這裏讓筆者給碰上了,如圖:html

prepub Full GC
prepub Full GC

可是預發機器和線上機器配置是不同的啊,預發是 Full GC 致使的 CPU 飆升不能表明線上機器也是這個緣由啊,爲了驗證此問題,筆者在其中一臺線上機器配置了 GC log 等參數,就等着線上問題再出現時能留下相關日誌信息,GC log 相關知識可參考: Understanding the Java Garbage Collection Log 。是否感受肉眼分析 GC log 很麻煩?好吧,早就有人作好了相關分析工具: GC easyjava

這裏提供一份 GC log,是在一臺線上 1Core 4G 的機器上採集的 (JVM 未調優),也是到了晚高峯 CPU 就 100% 了,能夠自行上傳到 GC easy 分析看看,點此 下載linux

一圖勝千言:
shell

Full GC
Full GC

爲了檢查是否有部分業務線程存在大幅使用 CPU 的狀況,筆者也順便準備了 生成線程轉儲 相關命令,如:先用 jps 找出 tomcat 的 pid,而後使用以下命令生成線程轉儲:tomcat

jstack -l <pid> > /opt/threadDump.txt複製代碼

爲了保證數據的準確性,在 CPU 被打滿的時間段內筆者生成了五六份以備後面分析,一樣,用肉眼觀察老是比較艱難,此處可利用 Java Thread Dump Analyzer 進行分析。這一塊在線上機器上的分析和筆者以前在預發機器上觀察的現象一致,沒有存在大量消耗 CPU 的問題線程。oracle

到此爲止,問題總算找到了,只要找到緣由所在,解決老是比較簡單的,以前因爲這組業務量不大,就沒有進行 JVM 調優,使用的默認的 JVM 相關參數,好比在 1Core 4G 的機器上,默認 最大堆內存 爲物理的內存的四分之一,還有不少內存沒有獲得利用,後面的解決辦法也不用寫了,調整後觀察了一週,到目前爲止晚高峯時服務依然很穩定,負載也在預期的範圍內,沒有再出現 CPU 飆升的狀況,問題獲得解決。工具

ELIMINATE CONSECUTIVE FULL GCs
深刻理解 Java 虛擬機(第2版)
Java 性能權威指南性能

原文地址spa

相關文章
相關標籤/搜索