記一次內(nèi)存溢出導(dǎo)致的生產(chǎn)事故

背景

因?yàn)橥碌碾x職,半路被迫接手的一個(gè)可視化項(xiàng)目,使用ElasticSearch作為OLAP數(shù)據(jù)庫、Docker作為部署工具等,突然有一天項(xiàng)目現(xiàn)場(chǎng)環(huán)境出現(xiàn)JVM內(nèi)存溢出問題,被迫披掛上陣定位問題的原因

分析過程

top命令查看系統(tǒng)資源占有情況,cpu占用不高,內(nèi)存占用高,并且虛擬內(nèi)存高達(dá)16g

https://upload-images.jianshu.io/upload_images/19453215-e57674319fd596ce.png

Tips:Java 程序由于自己維護(hù)堆的使用,導(dǎo)致調(diào)用 glibc 去管理內(nèi)存的次數(shù)較少。更糟的是 Java 8 開始使用 metaspace 原空間取代永久代,而元空間是存放在操作系統(tǒng)本地內(nèi)存中,那線程一多,每個(gè)線程都要使用一點(diǎn)元空間,每個(gè)線程都分配一個(gè)arena,每個(gè)都64MB,就會(huì)導(dǎo)致巨大的虛擬地址被分配。

free -h 查看內(nèi)存占有,buffer/cache占有很大,總內(nèi)存剩余7g

https://upload-images.jianshu.io/upload_images/19453215-8804a8d76a3e0f2e.png

Tips:buffers是用來緩沖塊設(shè)備做的,它只記錄文件系統(tǒng)的元數(shù)據(jù)(metadata)以及 tracking in-flight pages,而cached是用來給文件做緩沖。更通俗一點(diǎn)說:buffers主要用來存放目錄里面有什么內(nèi)容,文件的屬性以及權(quán)限等等。而cached直接用來記憶我們打開過的文件和程序。

通過系統(tǒng)日志中的java.lang.OutOfMemoryError與系統(tǒng)資源占用情況基本定位是jvm內(nèi)存溢出造成的

https://upload-images.jianshu.io/upload_images/19453215-e51b368aa85a1d24.png

進(jìn)一步使用jdk自帶性能監(jiān)控工具查找原因

  • jmap -heap 1 //查看堆內(nèi)存情況,無此命令參數(shù),因?yàn)樵摲?wù)使用的是docker鏡像的openjdk導(dǎo)致缺失部分jdk完整工具支持

    https://upload-images.jianshu.io/upload_images/19453215-e9887e6503cae81f.png
  • jstat -gc 1 250 10 //查看垃圾回收gc狀態(tài)情況,新生代與老年代內(nèi)存基本耗盡,F(xiàn)ullGC高達(dá)1200多次,但是未釋放成功

    https://upload-images.jianshu.io/upload_images/19453215-40948db5cfedd0b2.png
  • jmap -histo:live 1 | head -n 100 //查看top前100的實(shí)例數(shù)量情況,再次受阻,報(bào)錯(cuò)Unable to get pid

    https://upload-images.jianshu.io/upload_images/19453215-01a3c4cbf3510a5f.png

執(zhí)行jmap命令遇到的Unable to get pid可以采用的解決方案:

  • 在docker run時(shí)加上 --init 參數(shù)
  • 安裝Tini,使用tini作為入口進(jìn)程,配置啟動(dòng)java進(jìn)程

接下來,我們使用Alibaba開源的診斷工具Arthas可視化工具排查問題(PS:如果大家對(duì)Arthas不了解,可以查看官方文檔)

下載arthas全量jar>拷貝到容器內(nèi)>成功啟動(dòng)jar

docker cp 解壓絕對(duì)路徑 platform:/tmp/

docker exec -it  platform /bin/sh -c "cd /tmp/arthas; java -jar arthas-boot.jar"
https://upload-images.jianshu.io/upload_images/19453215-150b5fa682bae35f.png

執(zhí)行dashboard查看資源占有情況

https://upload-images.jianshu.io/upload_images/19453215-85fbede3b7181b9d.png

通過dashboard了解到資源已基本耗盡,線程執(zhí)行基本正常,最終需要通過導(dǎo)出dump文件分析內(nèi)存分布進(jìn)行分析

執(zhí)行heapdump /tmp/dump.hprof導(dǎo)出dump文件,下載dump文件到本地,通過MAT工具進(jìn)行分析

https://upload-images.jianshu.io/upload_images/19453215-e928fbf1d658ded8.png

最終定位問題是因?yàn)轫?xiàng)目中未正確使用緩存導(dǎo)致的

https://upload-images.jianshu.io/upload_images/19453215-ed4e1efcc5eb8edc.png

參考

mac下安裝MAT進(jìn)行分析
https://blog.csdn.net/hanchao5272/article/details/93379202

openjdk-alpine容器中的jvm如何執(zhí)行dump
http://www.crazy1984.com/2018/12/dev/20181227_docker_java_dump/

本文由博客一文多發(fā)平臺(tái) OpenWrite 發(fā)布!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容