一次非同步寫入kafka導致的偽記憶體洩漏

2021-09-24 19:14:01 字數 872 閱讀 9859

對應用進行壓測,剛開始幾分鐘tps很高能達到3000,壓了八分鐘後忽然降到了400多,十分奇怪,top看了一下cpu飆到了700%多。用jvisualvm連線上jvm進行監控,發現記憶體使用率高達90%多,然後在瘋狂gc,但是記憶體卻釋放不了。心中十分奇怪,難道是記憶體洩露了?於是檢視記憶體資訊,發現了大量hashmap.node和char物件在記憶體中。幾乎佔了70%記憶體,檢視日誌卻無異常。

一時間毫無頭緒,程式就是接受前端請求,然後http請求後台獲取結果再返回即可,然後會將請求資訊包裝成runnable任務提交給乙個非同步執行緒池,寫入kafka。之前測試也沒出現過這種問題,怎麼就記憶體洩漏了呢?仔細分析**中建立了hashmap的地方,怎麼也不應該無法gc**啊。偶然發現,kafka裡貌似沒有收到生產者訊息,難道是因為非同步傳送kafka的問題?

1、傳送任務列印失敗異常日誌,方便跟蹤

2、採用threadpoolexecutor建立乙個執行緒池,queuesize設定為10w,防止任務積壓把記憶體撐爆

3、把日誌級別調成debug,方便查詢問題

重新打包部署,再次測試,檢視日誌,傳送kafka報錯,連線不上leader直到60s超時,這就難怪了,執行緒都阻塞在這60s上了,佇列中任務越積越多,終於撐滿了記憶體。把kafka修好,再開始壓,神奇都事情出現了,記憶體不漲了,tps降到了400,檢視gc並不頻繁,這又是鬧哪齣?

top -hp pid隨便找了乙個占用cpu較高都執行緒,strace -cp tid看看這執行緒都幹了啥,發現99%的時間在mutex上,完了,這是在爭搶互斥鎖,我**裡沒用鎖啊???

靈光一現,難道debug模式列印日誌太多,n多業務執行緒爭搶乙個日誌檔案的reentrantlock鎖去寫日誌,導致鎖競爭了?調成info再試,tps重回3000!

當然,若是應用確實需要列印大量日誌,可以優化:

一次非同步處理

首發於 一次非同步處理 今天回憶了一下在做專案的時候遇到的乙個小問題。就是當兩個介面請求的資料相互沒有影響時,而你卻需要這兩個介面的所有資料,你會怎麼做呢?當我處理這個的時候想到的第乙個方案是這樣的。由於兩個介面相互沒有影響,我使用了乙個中間量進行判斷。是這樣寫的。var flag 2 請求資料1 ...

記一次Redis bitmap導致的miss問題

redis bitmaps 基礎概念 redis 記憶體淘汰機制 大致需求 指令碼批量匯入使用者資料到redis中,使用bitmap標記使用者是否在匯入的白名單中。使用者量級 億。key使用了分片處理,把key分成了10w個,每個key占用 1億 10w 1000 個bit。理想是key1用於標記u...

記一次Orika導致的OOM

有乙個專案執行一段時間後就會出現oom,下面梳理下尋找問題根源的方法 某一天,乙個好久沒動過的服務崩掉了,top檢視程序占用cpu高達700 按照top,jstack一條龍查詢導致異常的執行緒 這裡沒看到什麼異常,把堆檔案dump到本地進行分析 看到hashmap將近佔了記憶體大小的50 開始尋找專...