消失的Java進程-Linux OOM Killer

在一臺虛擬機上執行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

參考:http://www.vpsee.com/2013/10/how-to-configure-the-linux-oom-killer/

解決方案

在docker run命令中加入 -m 4000m,參考:https://jiajially.gitbooks.io/dockerguide/content/chapter_fastlearn/docker_run/-m.html,這個時候默認swap是8000m。

網絡上的方案:禁止OOM的方案

例如文章所寫:http://coolnull.com/3577.html

防止重要的系統進程觸發(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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章