性能文章>一则OOM死机故障的处理过程>

一则OOM死机故障的处理过程原创

1年前
748009

OOM是Out of Memory的简写,也就是内存不足。出现该问题的原因有很多,如程序内存泄漏等。内存泄漏问题可以通过定时地终止和重启有问题的程序来发现和解决。在比较新的Linux内核版本中,有一种名为OOM(Out Of Memory )杀手的算法,它可以在必要时执行Kill而杀掉一些程序。

故障现象

某服务器运行途中,屏幕显示如下错误:

image.png

可以看到终端显示“out of memory”, 并启动了内核的 OOM killer机制。
此时,虽然可以ping通,可可进行屏幕输入,但已无法进行本地或远程登陆了。只能强制重启。

故障分析

从屏幕上可以看到,swap已经为零。怀疑是内存耗尽问题。
咨询管理员该机器最近的状态情况:
引用
1、从free看,可用物理内存很低,cached和buffers都比较低;
2、swap使用率比较高,free swap很少,swap io交换比较频繁;
3、死机前一段时间,一些进程会不明原因的死掉。

观察系统日志,有如下的信息:

Nov  2 14:08:46 mail kernel: oom-killer: gfp_mask=0x1d2
Nov  2 14:09:52 mail kernel: Mem-info:
Nov  2 14:09:52 mail kernel: DMA per-cpu:
Nov  2 14:09:52 mail kernel: cpu 0 hot: low 2, high 6, batch 1
Nov  2 14:09:52 mail kernel: cpu 0 cold: low 0, high 2, batch 1
Nov  2 14:09:52 mail kernel: Normal per-cpu:
Nov  2 14:09:52 mail kernel: cpu 0 hot: low 30, high 90, batch 15
Nov  2 14:09:52 mail kernel: cpu 0 cold: low 0, high 30, batch 15
Nov  2 14:09:52 mail kernel: HighMem per-cpu: empty
Nov  2 14:09:52 mail kernel:
Nov  2 14:09:52 mail kernel: Free pages:       12744kB (0kB HighMem)
Nov  2 14:09:52 mail kernel: Active:2907 inactive:49122 dirty:0 writeback:0 unstable:0 free:3186 slab:2971 mapped:53302 pagetables:2777
Nov  2 14:09:52 mail kernel: DMA free:12292kB min:28kB low:56kB high:84kB active:0kB inactive:0kB present:16384kB pages_scanned:5855 all_unreclaimable? yes
Nov  2 14:10:47 mail kernel: protections[]: 0 0 0
Nov  2 14:10:47 mail kernel: Normal free:452kB min:460kB low:920kB high:1380kB active:11628kB inactive:196488kB present:245760kB pages_scanned:309375 all_unreclaimable? yes
Nov  2 14:10:47 mail kernel: protections[]: 0 0 0
Nov  2 14:10:47 mail kernel: HighMem free:0kB min:128kB low:256kB high:384kB active:0kB inactive:0kB present:0kB pages_scanned:0 all_unreclaimable? no
Nov  2 14:10:47 mail kernel: protections[]: 0 0 0
Nov  2 14:10:47 mail kernel: DMA: 5*4kB 4*8kB 3*16kB 3*32kB 3*64kB 3*128kB 1*256kB 0*512kB 1*1024kB 1*2048kB 2*4096kB = 12292kB
Nov  2 14:10:47 mail kernel: Normal: 1*4kB 6*8kB 1*16kB 8*32kB 2*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 452kB
Nov  2 14:10:50 mail kernel: HighMem: empty
Nov  2 14:10:52 mail kernel: Swap cache: add 13781061, delete 13781060, find 1725058/3421941, race 18+2545
Nov  2 14:10:54 mail kernel: Free swap:            0kB
Nov  2 14:10:55 mail kernel: 65536 pages of RAM
Nov  2 14:10:56 mail kernel: 0 pages of HIGHMEM
Nov  2 14:10:57 mail kernel: 1927 reserved pages
Nov  2 14:10:57 mail kernel: 2951 pages shared
Nov  2 14:11:01 mail kernel: 1 pages swap cached
Nov  2 14:11:02 mail kernel: Out of Memory: Killed process 22073 (mysqld).

报错信息和屏幕显示一直,并且后续一直报相同信息

Nov  2 14:55:51 mail kernel: Out of Memory: Killed process 23485 (httpd).
Nov  2 14:55:52 mail kernel: Out of Memory: Killed process 23471 (httpd).
Nov  2 17:06:25 mail kernel: Out of Memory: Killed process 23726 (smtp).

至此,能判断故障发生时,内核还处于可运行状态,但由于内存不足,触发了OOM killer机制,导致部分服务被强制终止而引发了问题。

故障处理

服务器启动后,可发现负载很高:

# uptime
12:33:17 up 1 day, 11:26,  1 user,  load average: 5.04, 90.02, 8.00

并且内存消耗很快。
1、使用top查询占用资源的进程;
经分析是amavisd-new调用的clamscan占用CPU和内存资源最高。而由于amavisd-new可同时启动5个病毒扫描进程,机器都在不断的忙于该操作。
2、查看进程的内容
使用lsof和ps命令分析其工作内容:

lsof -c clamscan|more
ps -ef --forest

经查找,5个进程均在对下述目录进行扫描:

/var/spool/vscan/tmp/

进入该目录后,发现目录容量不大,但小文件、目录比较多。
打开部分文件:

vi /var/spool/vscan/tmp/amavis-20071102T233954-03978/email.txt

均是mrtg的一个报错信息。(默认系统每5分钟运行一次mrtg扫描)
观察发现,5个进程在运行一段时间后并没有退出,也没有切换到其他目录,怀疑已因工作量太大被卡死。
3、停止服务
尝试用常规方式停止服务:

service clamd stop
service amavisd stop

服务被停止,但进程依旧存在,内存仍不断被消耗。只能终止相关进程:

lsof -p 4709
ps -ef|grep 4709
killall clamscan

命令运行成功后,系统负载恢复正常。
但重启两服务,扫描进程仍被卡死,问题依旧。
4、清空临时目录
采用相同的方式停止服务后,清空临时目录:

cd /var/spool/vscan/tmp/
rm -rf *

重启服务,系统压力正常。尝试平时的邮件发送等任务,病毒扫描过程正常。系统应已恢复。
关闭mrtg定时认为:

vi /etc/cron.d/mrtg

对系统进行持续观察,虽然运行正常,但内存被httpd、mysqld和amvisd消耗很快,建议用户增加物理内存。

总结

这次的故障属于典型的内存不足,导致发生OOM错误的情况。从系统状态和日常的监控以及系统日志的报错等都可发现踪迹,但缺没有引起足够的重视,最终导致死机。
另外,mrtg运行出错,而发送大量垃圾邮件,引起amavisd调用clamscan被卡的问题也使系统不堪负载。
类似的问题,需要针对系统进行监控以分析原因才能采取有效的措施。同时,管理员也不能忽视日常的维护工作,以免出现无可挽救的故障。

关闭OOM killer机制

在特定情况下,可能我们不希望核心执行OOM killer的工作。例如,排错。
则可以修改/etc/sysctl.conf,增加:

vm.oom-kill = 0

重启或执行sysctl -p即可生效。
若只是临时修改,可执行:

echo 0 > /proc/sys/vm/oom-kill
请先登录,感受更多精彩内容
快去登录吧,你将获得
  • 浏览更多精彩评论
  • 和开发者讨论交流,共同进步

为你推荐

字符串字面量长度是有限制的
前言 偶然在一次单元测试中写了一个非常长的字符串字面量。 正文 在一次单元测试中,我写了一个很长的字符串字面量,大概10万个字符左右,编译时,编译器给出了异常告警 `java: constant
多次字符串相加一定要用StringBuilder而不用-吗?
今天在写一个读取Java class File并进行分析的Demo时,偶然发现了下面这个场景(基于oracle jdk 1.8.0_144): ``` package test; public c
如何通过反射获得方法的真实参数名(以及扩展研究)
前段时间,在做一个小的工程时,遇到了需要通过反射获得方法真实参数名的场景,在这里我遇到了一些小小的问题,后来在部门老大的指导下,我解决了这个问题。通过解决这个问题,附带着我了解到了很多新的知识,我觉得
高吞吐、低延迟 Java 应用的 GC 优化实践
本篇原文作者是 LinkedIn 的 Swapnil Ghike,这篇文章讲述了 LinkedIn 的 Feed 产品的 GC 优化过程,虽然文章写作于 April 8, 2014,但其中的很多内容和
「每日五分钟,玩转 JVM」:久识你名,初居我心
聊聊 JVMJVM,一个熟悉又陌生的名词,从认识Java的第一天起,我们就会听到这个名字,在参加工作的前一两年,面试的时候还会经常被问到JDK,JRE,JVM这三者的区别。JVM可以说和我们是老朋友了
据说99.99%的人都会答错的类加载的问题
概述首先还是把问题抛给大家,这个问题也是我厂同学在做一个性能分析产品的时候碰到的一个问题。 同一个类加载器对象是否可以加载同一个类文件多次并且得到多个Class对象而都可以被java层使用吗请仔细注意
Java多线程——并发测试
编写并发程序时候,可以采取和串行程序相同的编程方式。唯一的难点在于,并发程序存在不确定性,这种不确定性会令程序出错的地方远比串行程序多,出现的方式也没有固定规则。那么如何在测试中,尽可能的暴露出这些问
Java多线程知识小抄集(一)
本文主要整理笔者遇到的Java多线程的相关知识点,适合速记,故命名为“小抄集”。本文没有特别重点,每一项针对一个多线程知识做一个概要性总结,也有一些会带一点例子,习题方便理解和记忆。 1.interr