1. 程式人生 > >一次FGC導致CPU飆高的排查過程

一次FGC導致CPU飆高的排查過程

    今天測試團隊反饋說,服務A的響應很慢,我在想,測試環境也會慢?於是我自己用postman請求了一下介面,真的很慢,竟然要2s左右,正常就50ms左右的。

    於是去測試伺服器看了一下,發現伺服器負載很高,並且該服務A佔了很高的cpu。先用top命令,看了load average,發現都到了1.5左右(雙核cpu)了,並且有一個java程序(20798)佔用cpu一直很高,如下圖:

    於是,用命令jps -l看了一下java的20798,剛好就是服務A。

    究竟服務A在跑什麼,畢竟是測試環境。於是使用top -Hp 20798看一下是哪個執行緒在跑,如下圖:

    

    發現執行緒20840佔用cpu非常高,其他幾乎都是0。通過以下命令輸出該執行緒id(20840)的16進位制:

printf "%x\n" 20840

  

輸出如下:

    執行緒id(20840)的16進位制是5186。

    然後使用以下命令打印出該執行緒的堆疊資訊:

jstack -l 20798 | grep -A 20 5168

  

    輸入如下:

    發現佔用cpu的程序是jvm的GC執行緒,於是猜測是不是由於一直在進行FGC導致cpu飆高,於是使用以下命令看下FGC的頻率和耗時:

jstat -gc 20798 1000

  

輸出如下:

    發現,果然是不斷地在進行著FGC,並且每次FGC的時間一直在升高。是什麼導致一直都在FGC呢?是有大物件一直在建立,回收不了?於是使用以下命令看下heap中的物件情況:

jmap -histo:live 20798 | head -20

  

輸出如下:

    發現一個業務類物件竟然有150w+個,並且佔用了264M的堆大小,什麼情況,並且這150w+個物件還是存活的(注意jmap使用的時候,已經帶上了:live選項,只輸出存活的物件),嚇我一跳。於是趕緊使用以下命令打出執行緒堆疊來看一下:

jstack -l 20798 > jstack_tmp.txt

  

輸出如下:

然後使用如下命令在輸出的執行緒堆疊中根據物件類查詢一下:

grep -C 30 'omments' jstack_tmp.txt

  

輸出如下:

    猜測是由於一下次從db load出了太多的CommentsEntity。

    於是使用以下命令dump出heapdump出來重複確認一下:

jmap -dump:live,format=b,file=news_busy_live.hprof 20798

  

    把heapdump檔案news_busy_live.hprof下載到windows本地,使用mat工具進行分析,第一次打開發現打不開,畢竟news_busy_live.hprof有3G那麼大,mat直接報OOM打不開,發現mat的配置檔案MemoryAnalyzer.ini裡面的配置-Xmx1024m,heap size才1G,太小了,於是改成-Xmx4096m,儲存,重新開啟mat,再開啟news_busy_live.hprof檔案即可,如下圖:

    發現mat已經幫我們分析出了記憶體洩漏的可以物件,233w+個物件(前面通過jmap命令輸出的150W+個,是後面為了寫文章而專門重現的操作,這裡的233w+個是當時真的出問題的時候dump出來的heap dump檔案),太恐怖了。

    通過以下操作,檢視

點選exclude all ....,因為弱引用,軟引用,虛引用等都可以被GC回收的,所以exclude,輸出如下:

    發現一共有6個執行緒引用了那233w+個物件,於是去前面dump出來的執行緒堆疊跟蹤以下這幾個執行緒的情況,發現堆疊裡面剛好這幾個執行緒也是在處理comments相關的邏輯,這個是剛好碰巧,一般執行緒id都對不上的,畢竟執行緒處理完之後就釋放了的。所以我們還是看回前面執行緒堆疊的資訊,這裡貼出根據關鍵字"omment"搜尋出來的執行緒堆疊的資訊,如下:

"XNIO-5 task-77" #248 prio=5 os_prio=0 tid=0x00007fc4511be800 nid=0x8f7 runnable [0x00007fc3e5af2000]   java.lang.Thread.State: RUNNABLE       ...        at cn.xxxxxx.news.commons.redis.RedisUtil.setZSet(RedisUtil.java:1080)        at cn.xxxxxx.news.service.impl.CommentsServiceV2Impl.setCommentIntoRedis(CommentsServiceV2Impl.java:1605)        at cn.xxxxxx.news.service.impl.CommentsServiceV2Impl.loadCommentsFromDB(CommentsServiceV2Impl.java:386)        ...        at cn.xxxxxx.xxxs.controller.vxxx.xxxxController.getxxxxxx(NewsContentController.java:404)        at cn.xxxxxx.xxx.controller.vxxx.xxxxxController$$FastClassBySpringCGLIB$$e7968481.invoke(<generated>)        ...        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)        at java.lang.Thread.run(Thread.java:745)​   Locked ownable synchronizers:        - <0x00000000f671ecd0> (a java.util.concurrent.ThreadPoolExecutor$Worker)​

  

    

    從上面的堆疊資訊,結合前面的猜測(猜測是一次性從db load出太多的CommentsEntity),猜測應該是函式loadCommentsFromDB一次性從db load出太多CommentsEntity了。於是看了一下業務程式碼,發現load出來的commentsEntity會放到redis的某一個zset,於是使用redis destopmanger看一下這個zset的資料,發現這個zset有22w的資料,從中找出幾條,發現對應的newsPk都是同一個,根據newsPk在db中找一下該newsPk的comments總記錄,發現該newsPk的comments記錄數是38w+條,那就是這個問題了,一次性從db中load了38w+的資料到記憶體。

    一次性load那麼多資料到記憶體,這肯定是一個慢查詢,不管是db還是網路io,都肯定很慢。然後發現業務程式碼還會有一個for迴圈,把這個CommentsEntityList遍歷一遍,一條一條放到redis,這也是一個非常慢的過程。

    然後我去看了服務A的access log,發現在短時間內,請求了該newsPk多次資料,所以就導致了jvm的heap空間不夠,然後出現不斷FGC的現象,並且該newsPk的請求,由於超時,都在閘道器超時返回了。

    為了驗證這個問題,我把相關的redis快取刪除,然後呼叫該newsPk的介面獲取資料,發現很慢,並且cpu立刻飈上去了,然後調多幾次,並且不斷地進行FGC,至此已經復現了該問題,和猜測的一樣。等資料load到redis之後,再訪問該介面,就很正常沒問題。

    上面發現問題的程式碼,找時間做一下優化才行,先重啟服務A,讓服務可用先。

 

                    歡迎關注微信公眾號“ismallboy”,請掃碼並關注以下公眾號,並在公眾號下面回覆“FGC”,獲得本文最新內容。

                                                           

相關推薦

FGC導致CPU排查過程

    今天測試團隊反饋說,服務A的響應很慢,我在想,測試環境也會慢?於是我自己用postman請求了一下介面,真的很慢,竟然要2s左右,正常就50ms左右的。     於是去測試伺服器看了一下,發現伺服器負載很高,並且該服務A佔了很高的cpu。先用

yarn導致cpu的異常排查經歷

yarn就先不介紹了,這次排坑經歷還是有收穫的,從日誌到堆疊資訊再到原始碼,很有意思,下面聽我說 問題描述: 叢集一臺NodeManager的cpu負載飆高。 程序還在但是看日誌已經不再向ResourceManager傳送心跳,不斷重複下文2的動作。 心跳停止一段時間後會重連上RM但是cpu仍然很高,再過

Linux(2)---記錄線上服務 CPU 100%的排查過程

Linux(2)---記錄一次線上服務 CPU 100%的排查過程 當時產生CPU飆升接近100%的原因是因為專案中的websocket時時斷開又重連導致CPU飆升接近100% 。如何排查的呢 是通過日誌輸出錯誤資訊: 得知websocket時時重新 連線的資訊,然後找到原因 解決了。 當然這

MongoDB 佔用 CPU問題的排查

1. 引言 今天檢視監控無意間突然發現自己的伺服器上,CPU 佔用率飆升到 100%,load 升到 10 以上,登入的響應已經達到半分鐘。 馬上執行 top,發現主要是 mongodb 佔用了大量

專案執行cpu處理

第一次處理這種問題,新手不懂的從何下手走了不少彎路,記錄一下,以後借鑑. 對於cpu執行過高的問題,首先要列印堆疊資訊,和執行緒執行cpu使用情況:    1.列印堆疊資訊:       先通過top -c找到自己的執行緒對應的id值:          jstac

再記 應用伺服器 CPU事故分析

## 一:背景 ### 1. 前言 大概有2個月沒寫部落格了,不是不想寫哈

服務器IO過處理過程

linux 服務器 緩沖區 io負載 記一次服務器IO過高處理過程 一、背景 在一次上線升級後,發現兩臺tomcat服務器的IOwait一直超過100ms,高峰時甚至超過300ms,檢查服務器發現CPU負載,內存的使用率都不高。問題可能出現在硬盤讀寫,而且那塊硬盤除了寫日誌外,沒有其他

怪異的業務卡頓排查過程

seq 用法 ipv 亂序 等於 瀏覽器 追蹤 cli tcp 上班的時候,突然被測試和產品加入了一個討論組,說有個問題需要我排查下,一頭霧水,於是開始進行了解和排查。 故障現象????客服人員使用該系統的其中幾個功能模塊的時候,彈出的溝通窗口會卡頓,並且關閉當前彈窗,返

堆外OOM問題的排查過程

轉載自   一次堆外OOM問題的排查過程 背景 線上服務有一臺機器訪問不通(一個管理平臺),在公司的服務治理平臺上檢視服務的狀況是正常的,說明程序還在。程序並沒有完全crash掉。去線上檢視機器日誌,發現了大量的OOM異常: 017-03-15 00:00:00.04

第一遇到死鎖——記程式卡住問題的錯誤排查過程

10月24日,週四   我負責的遊戲啟動程式(Launcher)更新上線後,臨下班前接到運營訊息,反映部分網咖啟動Launcher後無反應。跑到客服現場,通過QQ遠端桌面觀察到如下現象:雙擊程式圖示後,程式出現在工作管理員程序列表裡,但無任何其它反應,沒有任何介面彈出;然

ygc越來越慢的問題排查過程

開發十年,就只剩下這套架構體系了! >>>   

原創 記錄線上Mysql慢查詢問題排查過程

背景 前段時間收到運維反饋,線上Mysql資料庫凌晨時候出現慢查詢的報警,並把原始sql發了過來: --去除了業務含義的sql update test_user set a=1 where id=1; 表資料量200W左右,不是很大,而且是根據主鍵更新。 問題排查 排查Mysql資料庫 我看到sql後第一

線上服務CPU 100%的處理過程

## 告警 正在開會,突然釘釘告警聲響個不停,同時市場人員反饋客戶在投訴系統登不進了,報504錯誤。檢視釘釘上的告警資訊,幾臺業務伺服器節點全部報CPU超過告警閾值,達100%。 趕緊從會上下來,SSH登入伺服器,使用 `top` 命令檢視,幾個Java程序CPU佔用達到180%,190%,這幾個Java

生產環境CPU佔用問題解決

1 問題來源與背景 問題背景,專案對外提供查詢航班艙位介面,對航信黑屏報文做正則解析返回。由於起初對正則不熟悉,對黑屏報文格式規律不清楚,導致寫了大量的長正則表示式,生產環境併發量上來(200/s),直

ipv6導致Cisco6509cpu的處理過程

Cisco6509 cpu高 ipv6核心交換機是Cisco6509E,出現的問題是cpu從20%飆升到60%1、在Cisco6509上使用命令 show proc cpu sort 5min 可以查看到導致cpu高的原因是ipv6 input2、於是在Cisco6509下面的各個vlan抓包,共計12棟樓3

解Bug之路-記中介軟體導致的慢SQL排查過程

解Bug之路-記一次中介軟體導致的慢SQL排查過程 前言 最近發現線上出現一個奇葩的問題,這問題讓筆者定位了好長時間,期間排查問題的過程還是挺有意思的,正好部落格也好久不更新了,就以此為素材寫出了本篇文章。 Bug現場 我們的分庫分表中介軟體在經過一年的沉澱之後,已經到了比較穩定的階段。而且經過線上壓

解Bug之路-記中間件導致的慢SQL排查過程

有一個 bug 第一條 builder mstr 引入 i++ 原來 中間 解Bug之路-記一次中間件導致的慢SQL排查過程 前言 最近發現線上出現一個奇葩的問題,這問題讓筆者定位了好長時間,期間排查問題的過程還是挺有意思的,正好博客也好久不更新了,就以此為素材寫出了本篇文

CDN源站負載的問題排查及解決

https hit 兩個 ext 繼續 都是 cto 但是 指定節點 最近總是收到後端的CDN源站的負載高的報警,Apache經常會觸發重啟。於是啟動排查問題。 我們的CDN架構如下: 我們的CDN緩存策略是:使用源站的緩存策略,源站緩存策略是365天。 首先查看Apach

面試官問:平時碰到系統CPU和頻繁GC,你會怎麼排查

處理過線上問題的同學基本上都會遇到系統突然執行緩慢,CPU 100%,以及Full GC次數過多的問題。當然,這些問題的最終導致的

你要偷偷學會排查線上CPU的問題,然後驚豔所有人!

[GitHub 20k Star 的Java工程師成神之路,不來了解一下嗎!](https://github.com/hollischuang/toBeTopJavaer) [GitHub 20k Star 的Java工程師成神之路,真的不來了解一下嗎!](https://github.com/hollis