部署在linux上的java服務(wù)老是掛掉問題排查日志
最開始的時候,嚴重懷疑是內(nèi)存不足導(dǎo)致的,但是一直沒得排查,最近某個服務(wù)掛掉的幾率越來越高了不得不排查一下。
先從jar自己打印的debug,error查起,發(fā)現(xiàn)在掛掉之前沒有一點異常直接下一步(也沒想著這里能查到什么)畢竟“啟動成功、運行中突然掛,業(yè)務(wù)日志無異常”——99% 是進程被操作系統(tǒng)干掉或者 JVM 自己 Abort
直接上排查 "三部曲"
- 確認“是誰”殺進程
- 全局搜 JVM 崩潰日志
- 看 GC 日志有沒有“死循環(huán)”
1.確認“是誰”殺進程,看看是不是OOM Kill
什么是 OOM Kill ?
內(nèi)核選擇性殺掉某個進程來回收內(nèi)存,這個過程叫 OOM Kill
直接輸入下面的命令先查看
# 1. 系統(tǒng)日志里找 kill 記錄 sudo journalctl --since "1 hour ago" | egrep -i "killed process.*java|oom-killer"
這個指令的意思是:
在系統(tǒng)日志(journal)里,搜索最近 1 小時內(nèi),涉及 Java 進程被殺掉或觸發(fā) OOM Killer 的記錄。你可以通過修改journalctl --since "1 hour ago" 來實現(xiàn)查詢更久之前的,我這里掛了就馬上排查所有我只看1小時內(nèi)的免得有其它影響
通過命令可以看到系統(tǒng)返回給我們的信息

答案已經(jīng)呼之欲出了,警告信息:
Aug 13 14:21:32 VM-8-2-opencloudos kernel: sort invoked oom-killer: gfp_mask=0x140cca(GFP_HIGHUSER_MOVABLE|__GFP_COMP), order=0, oom_score_adj=0 Aug 13 14:21:32 VM-8-2-opencloudos kernel: Out of memory: Killed process 1461612 (java) total-vm:3390404kB, anon-rss:755084kB, file-rss:12044kB, shmem-rss:0kB, UID:0 pgtables:1964kB oom_score_adj:0
看到Out of memory:就表示系統(tǒng)內(nèi)存不夠了
Killed process 1461612 (java):內(nèi)核殺掉了 PID=1461612 的 Java 進程
果然,oom kill了,系統(tǒng)主動殺了一個占用內(nèi)存大的進程,也就是掛掉的那個服務(wù)
所以 Java 應(yīng)用會莫名其妙掛掉,也不會生成 JVM hs_err_pid.log,因為這是 操作系統(tǒng)級別的強殺,JVM 根本沒機會寫日志.
還有另一種方式,直接查看內(nèi)核緩沖區(qū)日志,跟上面那個方式差不多
# 2. 內(nèi)核環(huán)形緩沖區(qū) dmesg -T | egrep -i "killed process|oom_reaper|segfault

從該指令返回的信息我們可以看到這幾個時間都發(fā)生了 OOM Kill 都因為內(nèi)存不足導(dǎo)致的
使用命令查看我們內(nèi)存使用情況
free -h

逐項分析:(但是著重看 used 和 available)
total 3.6Gi
物理內(nèi)存總?cè)萘浚捍蠹s 3.6 GB(可能是 4GB 物理內(nèi)存減去一些保留給內(nèi)核/顯存的空間)。
used 3.5Gi
當(dāng)前已使用的內(nèi)存(包含應(yīng)用、緩存等)。
free 120Mi
完全空閑、未分配的內(nèi)存(非常少)。
shared 3.4Mi
共享內(nèi)存占用(主要是 tmpfs、shm)。
buff/cache 157Mi
文件緩存、緩沖區(qū)(可被回收)。
available 81Mi
系統(tǒng)真正還能分配給應(yīng)用程序的內(nèi)存:只有 81MB,這個值低到隨時會觸發(fā) OOM。
我們還可以通過下面的指令查看是誰吃的內(nèi)存這么多,我這里是這幾個java服務(wù)吃最多,吃完了
# 按內(nèi)存占用排序 ps aux --sort=-%mem | head -20
-----------------------------------------------------------------------
這種情況加內(nèi)存是最有效的方式
但是,我還想掙扎一下,我決定做這兩步:
1.打開Swap, 開 2G 的swap
sudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile
開機自啟 swap
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
這樣你就會獲得2G內(nèi)存(消耗2G存儲空間)
2.限制開銷不大的服務(wù)最大堆的空間
把512m 改成 256m

第一步排查就已經(jīng)查到問題了,三部曲都沒走完,但是不是每一個人都是這種情況,下面兩部也簡單說一下
2.全局搜 JVM 崩潰日志
如果你不是 oom kill 導(dǎo)致的,那么jvm可能在"臨kill"前會給你留下線索
# 最近 7 天內(nèi)所有 hs_err 文件 sudo find / -type f -name "hs_err*.log" -mtime -7 2>/dev/null
文件名匹配模式,找類似
hs_err_pid12345.log這樣的文件。這些一般是 Java 虛擬機(JVM)崩潰時生成的錯誤日志,里面會有堆棧、CPU、內(nèi)存等信息。
然后分析這些日志排查一下
3.看 GC 日志有沒有“死循環(huán)”
如果你沒有打開GC日志,那你得在jar包啟動指令上面加上下面這個指令,下次復(fù)現(xiàn)時就能拿到日志了
JAVA_OPTS="$JAVA_OPTS -Xloggc:$APP_HOME/logs/gc_%t.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps"
等下次復(fù)現(xiàn)之后就可以輸入下面的指令查看了
grep -c "Full GC" logs/gc_*.log
總結(jié)
到此這篇關(guān)于部署在linux上的java服務(wù)老是掛掉問題排查日志的文章就介紹到這了,更多相關(guān)linux上java服務(wù)老是掛掉內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用redisTemplate從redis獲取所有數(shù)據(jù)
這篇文章主要介紹了使用redisTemplate從redis獲取所有數(shù)據(jù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06
springboot打包JAR包瘦身lib和配置文件分離方式
本文介紹了如何通過優(yōu)化POM.xml配置來減小JAR包大小,提高傳輸速度,主要步驟包括:指定打包環(huán)境和跳過編譯單元測試、JAR打包排除配置文件和lib、提供全量包便于開發(fā)環(huán)境使用、將lib和配置文件單獨復(fù)制出來2024-11-11
Java編程Iterator迭代器設(shè)計原理及實現(xiàn)代碼示例
這篇文章主要介紹了Java編程Iterator迭代器設(shè)計原理及實現(xiàn)代碼示例,具有一定參考價值,需要的朋友可以了解下。2017-10-10

