一次頻繁Full GC問題排查過程分享

問題描述

  • 應(yīng)用收到頻繁Full GC告警

問題排查

  • 登錄到對應(yīng)機器上去,查看GC日志恰响,發(fā)現(xiàn)YGC一分鐘已經(jīng)達到了15次凫佛,比Full GC還要頻繁一些语婴,其中Full GC平均10分鐘超過了4次,如下圖

    image
  • 使用jstat -gcutil 5280 1000查看實時GC情況溶握,年老代采用的是CMS收集器杯缺,發(fā)現(xiàn)觸發(fā)Full GC的原因是年老代占用空間達到指定閾值70%(-XX:CMSInitiatingOccupancyFraction=70)。
  • 這時候猜測是某個地方頻繁創(chuàng)建對象導(dǎo)致睡榆,通過jmap -dump:format=b,file=temp.dump 5280 dump文件萍肆,然后下載到本地通過jvisualvm分析對象的引用鏈的方式來定位具體頻繁創(chuàng)建對象的地方袍榆,dump文件下載下來有5G多,整個導(dǎo)入過程都花了10多分鐘塘揣。想查看所占空間較多對象的引用鏈包雀,直接OOM了,dump對象太大了亲铡。這時候就換了種思路馏艾,查看占用空間比較大的一系列對象,看能不能找出什么端倪奴愉。占用空間最大的幾類對象如下圖

    image

    發(fā)現(xiàn)排第一的chart[]對象里面琅摩,存在一些metrics監(jiān)控的具體指標(biāo)的相關(guān)內(nèi)容,排第二的io.prometheus.client.Collector$MetricFamilySample$Sample和排第9和第13對象都是spring boot中metrics指標(biāo)監(jiān)控相關(guān)的對象锭硼,所以此時懷疑metrics監(jiān)控的某個地方在頻繁創(chuàng)建對象房资,首先考慮的是否因為metrics指標(biāo)太多導(dǎo)致的,于是登錄線上機器curl localhost:8080/mertrics > metrics.log檀头,發(fā)現(xiàn)響應(yīng)內(nèi)容有50多M轰异,參考其他相關(guān)的正常應(yīng)用,指標(biāo)總共內(nèi)容也就10多M左右暑始,打開指標(biāo)內(nèi)容發(fā)現(xiàn)了很多類似如下圖的指標(biāo)

    image


    看到了這里已經(jīng)可以確定代碼中上報這個指標(biāo)是存在問題的搭独,并沒有達到我們想要的效果,所以也懷疑也是這個地方導(dǎo)致的Full GC頻繁廊镜。

問題初步解決

  • 由于這個指標(biāo)也無關(guān)緊要牙肝,初步解決方案就把上報該指標(biāo)的代碼給干掉。上線后看下Full GC問題是否會得到改善嗤朴,果然配椭,上線后Full GC告警問題已經(jīng)解決。

初步解決后的思考雹姊,為什么會有這個問題股缸?

  • 外部監(jiān)控系統(tǒng),每25s會來調(diào)用metrics這個接口吱雏,這個接口會把所有的metrics指標(biāo)轉(zhuǎn)成字符串然后作為http響應(yīng)內(nèi)容響應(yīng)敦姻。監(jiān)控每來調(diào)用一次就會產(chǎn)生一個50多M的字符串,導(dǎo)致了頻繁YGC歧杏,進而導(dǎo)致了晉升至年老代的對象也多了起來镰惦,最終年老代內(nèi)存占用達到70%觸發(fā)了Full GC。

根源問題重現(xiàn)

  • 此處采用metrics的作用:統(tǒng)計線程池執(zhí)行各類任務(wù)的數(shù)量得滤。為了簡化代碼陨献,用一個map來統(tǒng)計,重現(xiàn)代碼如下
    import java.util.Map;
    import java.util.concurrent.*;
    import java.util.concurrent.atomic.AtomicInteger;
    
    /**
     * 線程池通過submit方式提交任務(wù)懂更,會把Runnable封裝成FutureTask眨业。
     * 直接導(dǎo)致了Runnable重寫的toString方法在afterExecute統(tǒng)計的時候沒有起到我們想要的作用急膀,
     * 最終導(dǎo)致幾乎每一個任務(wù)(除非hashCode相同)就按照一類任務(wù)進行統(tǒng)計。所以這個metricsMap會越來越大龄捡,調(diào)用metrics接口的時候卓嫂,會把該map轉(zhuǎn)成一個字符返回
     */
    public class GCTest {
        /**
         * 統(tǒng)計各類任務(wù)已經(jīng)執(zhí)行的數(shù)量
         * 此處為了簡化代碼,只用map來代替metrics統(tǒng)計
         */
        private static Map<String, AtomicInteger> metricsMap = new ConcurrentHashMap<>();
    
        public static void  main(String[] args) throws InterruptedException {
            ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 10, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<>()){
                /**
                 * 統(tǒng)計各類任務(wù)執(zhí)行的數(shù)量
                 * @param r
                 * @param t
                 */
                @Override
                protected void afterExecute(Runnable r, Throwable t) {
                    super.afterExecute(r, t);
                    metricsMap.compute(r.toString(), (s, atomicInteger) ->
                            new AtomicInteger(atomicInteger == null ? 0 : atomicInteger.incrementAndGet()));
                }
            };
            /**
             * 源源不斷的任務(wù)添加進線程池被執(zhí)行
             */
            for (int i =0; i < 1000; i++) {
                threadPoolExecutor.submit(new SimpleRunnable());
            }
            Thread.sleep(1000 * 2);
            System.out.println(metricsMap);
            threadPoolExecutor.shutdownNow();
        }
        static class SimpleRunnable implements Runnable{
    
            @Override
            public void run() {
                System.out.println("SimpleRunnable execute success");
            }
            /**
             * 重寫toString用于統(tǒng)計任務(wù)數(shù)
             * @return
             */
            @Override
            public String toString(){
                return this.getClass().getSimpleName();
            }
        }
    }

最終解決

  • 把submit改成execute即可

總結(jié)

  • 以上重顯代碼可以看出metricsMap中的元素是會越來越多的聘殖。如果就這樣下去晨雳,最終的結(jié)果也會出現(xiàn)OOM。
  • 根本原因還是對ThreadPoolExecutor不夠熟悉奸腺,所以出現(xiàn)了這次問題餐禁。
  • 個人感覺Full GC類問題是比較讓人頭疼的。這些問題并不會想代碼語法問題一樣突照,ide會提示我們具體錯在哪里帮非,我們只要修改對應(yīng)地方基本都能解決。造成Full GC頻繁的原因也有很多讹蘑,比如可能是jvm參數(shù)設(shè)置不合理末盔、Metaspace空間觸發(fā)、頻繁創(chuàng)建對象觸發(fā)等等座慰。
  • 如果確定了是頻繁創(chuàng)建對象導(dǎo)致陨舱,那么接下來的目的就是確定頻繁創(chuàng)建對象的對應(yīng)代碼處,這時候可以選擇通過dump線上堆棧版仔,然后下載到本地游盲。選擇一些可視化分析工具進行分析。最終定位到出問題的代碼處邦尊,然后解決問題背桐。

版權(quán)聲明
作者:wycm
github:https://github.com/wycm
出處:http://www.reibang.com/p/3f7a4d33b121
您的支持是對博主最大的鼓勵,感謝您的認真閱讀蝉揍。
本文版權(quán)歸作者所有,歡迎轉(zhuǎn)載畦娄,但未經(jīng)作者同意必須保留此段聲明又沾,且在文章頁面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利熙卡。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末杖刷,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子驳癌,更是在濱河造成了極大的恐慌滑燃,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件颓鲜,死亡現(xiàn)場離奇詭異表窘,居然都是意外死亡典予,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門乐严,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瘤袖,“玉大人,你說我怎么就攤上這事昂验∥娴校” “怎么了?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵既琴,是天一觀的道長占婉。 經(jīng)常有香客問我,道長甫恩,這世上最難降的妖魔是什么逆济? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮填物,結(jié)果婚禮上纹腌,老公的妹妹穿的比我還像新娘。我一直安慰自己滞磺,他們只是感情好升薯,可當(dāng)我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著击困,像睡著了一般涎劈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上阅茶,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天蛛枚,我揣著相機與錄音,去河邊找鬼脸哀。 笑死蹦浦,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的撞蜂。 我是一名探鬼主播盲镶,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蝌诡!你這毒婦竟也來了溉贿?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤浦旱,失蹤者是張志新(化名)和其女友劉穎宇色,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡宣蠕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年例隆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片植影。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡裳擎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出思币,到底是詐尸還是另有隱情鹿响,我是刑警寧澤,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布谷饿,位于F島的核電站惶我,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏博投。R本人自食惡果不足惜绸贡,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望毅哗。 院中可真熱鬧听怕,春花似錦、人聲如沸虑绵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽翅睛。三九已至声搁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間捕发,已是汗流浹背疏旨。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留扎酷,地道東北人檐涝。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像法挨,于是被迫代替她去往敵國和親骤铃。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內(nèi)容