監控系統發現服務掛掉, 登上機器ps -ef|grep **
發現程序還在,因為監控系統是通過心跳檢測來監控服務的存活狀態的,服務假死
1、df、free、top 三連
磁碟空間正常、記憶體使用率正常、某個程序的cpu佔用率達300%多
2、top -h-p pid
檢視占用cpu最高的程序對應執行緒,得到執行緒id tid
3、printf 『%x』 tid
執行緒id轉為16進製制
4、jstack pid | grep -c 5 tid
檢視程序中占用cpu最高的執行緒,發現是gc執行緒
"gc task thread#0 (parallelgc)" os_prio=0 tid=0x00007f181001d800 nid=0x31a7 runnable
"gc task thread#1 (parallelgc)" os_prio=0 tid=0x00007f181001f800 nid=0x31a8 runnable
"gc task thread#2 (parallelgc)" os_prio=0 tid=0x00007f1810021800 nid=0x31a9 runnable
"gc task thread#3 (parallelgc)" os_prio=0 tid=0x00007f1810023000 nid=0x31aa runnable
5、jstat -gc pid 500
查下gc情況,發現幾乎每秒發生一次full gc
6、jmap -dump:format=b,file=/tmp/**.dump pid
dump出jvm堆記憶體資料
7、通過mat(eclipse memory analysis tools)分析dump檔案
匯入dump檔案分析後,發現有兩大塊資料異常,占用了整個堆記憶體的80%
第一塊是下面109.8mb的這個,繼續分析是com.mysql.jdbc.jdbc4resultset
這個物件占用的,通過**最終定位到問題,是乙個定時任務批量處理資料時沒有分頁處理,一次查出了80w+的資料,然後遍歷處理,導致gc時記憶體不能得到釋放,這裡改為分頁處理後,問題解決
第二塊是com.alibaba.druid.stat.jdbcdatasourcestat
這個物件占用了210.3mb。從名字可以看出這個類是druid用做統計的,他會記錄最近n(預設1000)條的sql執**況,sqlstatmap
這個map是記錄了最近1000條的sql的執**況,看看**:
sqlstatmap = new linkedhashmap(16, 0.75f, false)
}return remove;}};
但是從圖里可以看出這裡其實只記錄了203條sql的執**況,卻占用了200多mb,理應沒有這麼大的,sqlstatmap的key其實就是我們執行的sql,繼續看sqlstatmap裡面的值,發現了幾個特別大的key,sql內容是這樣的update t_table set a=b where id in (id1,id2,id3....)
,這條sql的查詢條件in裡面包含了幾十萬個id,占用空間10多mb,所以導致了sqlstatmap占用空間大
所以這裡的解決辦法是:
1、先關閉druid的統計功能(我們並沒有用到這個功能),釋放jdbcdatasourcestat
的記憶體占用;
p:filters="stat"
p:connectionproperties="config.decrypt=true"/>
2、優化業務處理,採用分頁的方式處理
記一次pending請求問題查詢過程
情景再現 近期發現 訪問變慢,經常會出現請求無法響應的問題,乙個請求長時間沒有返回,導致頁面出現504 gateway timeout 我們使用的nodejs ngnix 反向 猜測原因 伺服器記憶體使用過高,導致伺服器處理緩慢?併發請求過多導致請求緩慢?定位問題 檢視伺服器cpu和記憶體使用情況 ...
記一次線上OOM問題
首先是 jmap dump format b,file file.hprof 匯入mat工具 定位的問題是 standardmanager和standardsession檢視原始碼發現concurrenthashmap node就是standardmanager的session屬性 protecte...
記一次Orika導致的OOM
有乙個專案執行一段時間後就會出現oom,下面梳理下尋找問題根源的方法 某一天,乙個好久沒動過的服務崩掉了,top檢視程序占用cpu高達700 按照top,jstack一條龍查詢導致異常的執行緒 這裡沒看到什麼異常,把堆檔案dump到本地進行分析 看到hashmap將近佔了記憶體大小的50 開始尋找專...