記一次記憶體溢位導致的生產事故
背景
因為同事的離職,半路被迫接手的一個視覺化專案,使用ElasticSearch作為OLAP資料庫、Docker作為部署工具等,突然有一天專案現場環境出現JVM記憶體溢位問題,被迫披掛上陣定位問題的原因
分析過程
top
命令檢視系統資源佔有情況,cpu佔用不高,記憶體佔用高,並且虛擬記憶體高達16g
Tips:Java 程式由於自己維護堆的使用,導致呼叫 glibc 去管理記憶體的次數較少。更糟的是 Java 8 開始使用 metaspace 原空間取代永久代,而元空間是存放在作業系統本地記憶體中,那執行緒一多,每個執行緒都要使用一點元空間,每個執行緒都分配一個arena,每個都64MB,就會導致巨大的虛擬地址被分配。
free -h
檢視記憶體佔有,buffer/cache佔有很大,總記憶體剩餘7g
Tips:buffers是用來緩衝塊裝置做的,它只記錄檔案系統的後設資料(metadata)以及 tracking in-flight pages,而cached是用來給檔案做緩衝。更通俗一點說:buffers主要用來存放目錄裡面有什麼內容,檔案的屬性以及許可權等等。而cached直接用來記憶我們開啟過的檔案和程式。
通過系統日誌中的java.lang.OutOfMemoryError
與系統資源佔用情況基本定位是jvm記憶體溢位造成的
進一步使用jdk自帶效能監控工具查詢原因
jmap -heap 1 //檢視堆記憶體情況,
無此命令引數
,因為該服務使用的是docker映象的openjdk導致缺失部分jdk完整工具支援jstat -gc 1 250 10 //檢視垃圾回收gc狀態情況,新生代與老年代記憶體基本耗盡,FullGC高達
1200
多次,但是未釋放成功jmap -histo:live 1 | head -n 100 //檢視top前100的例項數量情況,再次受阻,報錯
Unable to get pid
執行jmap
命令遇到的Unable to get pid
可以採用的解決方案:
- 在docker run時加上
--init
引數 - 安裝
Tini
,使用tini作為入口程式,配置啟動java程式
接下來,我們使用Alibaba開源的診斷工具Arthas視覺化工具排查問題(PS:如果大家對Arthas不瞭解,可以檢視官方文件)
下載arthas全量jar>拷貝到容器內>成功啟動jar
docker cp 解壓絕對路徑 platform:/tmp/
docker exec -it platform /bin/sh -c "cd /tmp/arthas; java -jar arthas-boot.jar"
執行dashboard
檢視資源佔有情況
通過dashboard
瞭解到資源已基本耗盡,執行緒執行基本正常,最終需要通過匯出dump檔案分析記憶體分佈進行分析
執行heapdump /tmp/dump.hprof
匯出dump檔案,下載dump檔案到本地,通過MAT工具進行分析
最終定位問題是因為專案中未正確使用快取導致的
參考
mac下安裝MAT進行分析
連結:https://www.jianshu.com/p/88469f8f9a70
openjdk-alpine容器中的jvm如何執行dump
連結:http://www.crazy1984.com/2018/12/dev/20181227_docker_java_dump/
本文由部落格一文多發平臺 OpenWrite 釋出!
相關文章
- 記一次Orika使用不當導致的記憶體溢位記憶體溢位
- Java記憶體溢位OutOfMemoryError的產生與排查Java記憶體溢位Error
- Android-Fragment 切換造成記憶體溢位,導致記憶體增長AndroidFragment記憶體溢位
- 一次JVM記憶體問題導致的線上事故JVM記憶體
- Java棧溢位|記憶體洩漏|記憶體溢位Java記憶體溢位
- 記憶體溢位記憶體溢位
- 記一次 .NET 某婦產醫院 WPF記憶體溢位分析記憶體溢位
- 記錄佇列序列化模型導致的記憶體溢位的解決方案佇列模型記憶體溢位
- Java記憶體溢位Java記憶體溢位
- 記憶體溢位和記憶體洩露記憶體溢位記憶體洩露
- 記一次排序導致的記憶體危機排序記憶體
- 強如 Disruptor 也發生記憶體溢位?記憶體溢位
- 【記憶體洩漏和記憶體溢位】JavaScript之深入淺出理解記憶體洩漏和記憶體溢位記憶體溢位JavaScript
- 因為 int32 溢位導致的 peewee.IntegrityError 錯誤事故記錄Error
- JVM——記憶體洩漏與記憶體溢位JVM記憶體溢位
- 為什麼 Go 中有的自定義 error 會導致記憶體溢位GoError記憶體溢位
- JavaScript之記憶體溢位和記憶體洩漏JavaScript記憶體溢位
- 日誌導致jvm記憶體溢位相關問題JVM記憶體溢位
- 記一次 .NET 醫院CIS系統 記憶體溢位分析記憶體溢位
- java記憶體溢位和記憶體洩漏的區別Java記憶體溢位
- JAVA記憶體區域與記憶體溢位異常Java記憶體溢位
- [Java基礎]記憶體洩漏和記憶體溢位Java記憶體溢位
- 記一次網頁記憶體溢位分析及解決實踐網頁記憶體溢位
- 關於 PHP 記憶體溢位的思考PHP記憶體溢位
- 阿里大佬講解Java記憶體溢位示例(堆溢位、棧溢位)阿里Java記憶體溢位
- jvm記憶體設定及記憶體溢位、解決方案JVM記憶體溢位
- return new物件造成溢位記憶體物件記憶體
- mybatis-plus getOne 記憶體溢位MyBatis記憶體溢位
- JVM(2)-Java記憶體區域與記憶體溢位異常JVMJava記憶體溢位
- 記一次記憶體溢位問題的排查、分析過程及解決思路記憶體溢位
- 簡單的記憶體“洩露”和“溢位”記憶體
- Executors使用不當引起的記憶體溢位記憶體溢位
- 記憶體和棧溢位問題定位記憶體
- Windbg下使用dump分析記憶體溢位記憶體溢位
- php記憶體溢位了怎麼辦?PHP記憶體溢位
- Redis 報”OutOfDirectMemoryError“(堆外記憶體溢位)RedisError記憶體溢位
- Windows Tomcat 記憶體溢位解決方法WindowsTomcat記憶體溢位
- 記一次 vue 的非同步更新佇列導致記憶體洩漏Vue非同步佇列記憶體