記一次內存飆升的Windbg

背景

突然間接到運維的報警,我們一個服務,內存找過了6GB的佔用。才6GB 也不是很大,因爲在處理別的事情,服務dump一下暫時一放,然後半小時之後,接到了運維的Kafka堆積報警。然後切換着重啓了一下兩個節點,Kafka消費速率回覆正常,內存也從500M攀升到2GB後逐漸穩定。當天半夜,運維又報警,不過已經熟睡的我,並沒有第一時間響應,第二天觀察了一下服務,發現內存已經迴歸到了2GB左右。

內存飆升 與 Kafka堆積是否是一件事情

拉出表格來對比一下時間發現,這兩個事情,時間節點基本上是能對的上的,所以大概率是一件事情。


dump分析

這麼看來只要解了內存飆升的問題,Kafka堆積的問題應該也就會一併解決。那麼,我們來分析一下,爲什麼會出現內存飆升吧。

首先看一下內存的整體使用情況

!dumpheap -stat

發現跟字符串關係很大,下邊的Free應該是內存釋放了,但是GC還沒有及時回收的內存。

字符串1GB + 未回收內存3GB + 其他 林林總總 約等於 6G,差不多。下面我們重點追查一下這個字符串是怎麼回事。

!DumpHeap -mt 000007fef956aee0 -min 200

出現了大量的 500Byte左右大小的字符串。這個大小,感覺像是業務字符串,並且應該是不重複的。先隨便搞一條出來看看。

!do 000000008966ee78

這個內容有點莫名的眼熟,這不是我們發送消息給釘釘,然後再查詢一下,釘釘的消息發送結果的返回值嘛?大概已經知道,是哪段邏輯出的錯了,代碼雖然不是我寫的,但是我大概知道有這麼一段邏輯。可是這段爲什麼會讓內存暴增呢?查一下引用堆棧。

!GCRoot 000000008966ee78

發現上層的引用是一個List,我們打印一下這個List看看。

!DumpObj 0000000313b371a0

發現這個List好像是不小,12000+。粗略算算 12000 * 500 / GB 大概 5.xGB,但是現在內存只用了1GB多點,分析一下源碼。

那個List 應該就是對應了這個tasks對象了。


後邊會把查詢的數據,序列化,然後放到這個對象上,在插入到數據庫中。

簡單總結一下原因,是因爲一次性取出來的對象有點多(12000)條,然後挨個查詢他的消息的發送結果,然後將網絡調用的查詢結果,序列化到對象上,然後再保存到數據庫中。因爲這些Model都被引用在一個List中,所以當12000個數據全都被處理完成之後纔會釋放List的內存。這樣,每次處理,內存都跟坐過山車一樣。

問題定位到了,解決方式就很簡單了,隨便搞。

啊,又解決一個問題,我變強了。

我的掘金 https://juejin.im/post/6868466964378222599/

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