在一臺虛擬機上執行docker java應用,每隔一段時間就會出現java行程消失、而且沒有任何jvm error log的情況,
略一尋思,應該是遇到網上常說的Linux OOM的情況:虛擬機10G,docker默認分配記憶體未做限制,
原因定位
去服務器上執行:dmesg | grep java,果然有資料
并且查看檔案: /var/log/messages 定位關鍵字:oom-killer,
看到相關資訊:java pid資訊,
memory: usage 2047696kB, limit 2047696kB, failcnt 23543
memory+swap: usage 2047696kB, limit 9007199254740991kB, failcnt 0
......
Free swap = 0kB
Total swap = 0kB
......
Memory cgroup out of memory: Kill process 18286 (java) score 933 or sacrifice child
復制代碼
最終java行程被Linux OOM弄死了:因為oom的score太高了:933,啟動的時候score是225,行程的oom_score 分數越高,越容易被 OOM Killer 殺掉,使用如下腳本檢測oom score:
# vi oomscore.sh
#!/bin/bash
for proc in $(find /proc -maxdepth 1 -regex '/proc/[0-9]+'); do
printf "%2d %5d %s\n" \
"$(cat $proc/oom_score)" \
"$(basename $proc)" \
"$(cat $proc/cmdline | tr '\0' ' ' | head -c 50)"
done 2>/dev/null | sort -nr | head -n 10
# chmod +x oomscore.sh
復制代碼
解決方案
在docker run命令中加入 -m 4000m ,未加這個時候默認swap是8000m,
網路上的方案:禁止OOM的方案
防止重要的系統行程觸發(OOM)機制而被殺死:可以設定引數/proc/PID/oom_adj為-17,可臨時關閉linux內核的OOM機制,內核會通過特定的演算法給每個行程計算一個分數來決定殺哪個行程,每個行程的oom分數可以/proc/PID/oom_score中找到,我們運維程序中保護的一般是sshd和一些管理agent,
保護某個行程不被內核殺掉可以這樣操作:
# echo -17 > /proc/$PID/oom_adj
復制代碼
如何防止sshd被殺,可以這樣操作:
# pgrep -f "/usr/sbin/sshd" | while read PID;do echo -17 > /proc/$PID/oom_adj;done
復制代碼
可以在計劃任務里加入這樣一條定時任務,就更安全了:
#/etc/cron.d/oom_disable
*/1**** root pgrep -f "/usr/sbin/sshd" | while read PID;do echo -17 > /proc/$PID/oom_adj;done
復制代碼
為了避免重啟失效,可以寫入/etc/rc.d/rc.local
echo -17 > /proc/$(pidof sshd)/oom_adj
復制代碼
至于為什么用-17而不用其他數值(默認值為0),這個是由linux內核定義的,查看內核原始碼可知:
以linux-3.3.6版本的kernel原始碼為例,路徑為linux-3.6.6/include/linux/oom.h,閱讀內核原始碼可知oom_adj的可調值為15到-16,其中15最大-16最小,-17為禁止使用OOM,oom_score為2的n次方計算出來的,其中n就是行程的oom_adj值,所以oom_score的分數越高就越會被內核優先殺掉,
當然還可以通過修改內核引數禁止OOM機制
# sysctl -w vm.panic_on_oom=1
vm.panic_on_oom = 1 //1表示關閉,默認為0表示開啟OOM
# sysctl -p
復制代碼
看完三件事??
如果你覺得這篇內容對你還蠻有幫助,我想邀請你幫我三個小忙:
-
點贊,轉發,有你們的 『點贊和評論』,才是我創造的動力,
-
關注公眾號 『 java爛豬皮 』,不定期分享原創知識,
-
同時可以期待后續文章ing??
出處:club.perfma.com/article/185…
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/182755.html
標籤:其他
