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

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

2年前
815909

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
点赞收藏
兔兔七
请先登录,感受更多精彩内容
快去登录吧,你将获得
  • 浏览更多精彩评论
  • 和开发者讨论交流,共同进步

为你推荐

记一次“雪花算法”造成的生产事故的排查记录

记一次“雪花算法”造成的生产事故的排查记录

重新认识下JVM级别的本地缓存框架Guava Cache——优秀从何而来

重新认识下JVM级别的本地缓存框架Guava Cache——优秀从何而来

解读JVM级别本地缓存Caffeine青出于蓝的要诀 —— 缘何会更强、如何去上手

解读JVM级别本地缓存Caffeine青出于蓝的要诀 —— 缘何会更强、如何去上手

解读JVM级别本地缓存Caffeine青出于蓝的要诀2 —— 弄清楚Caffeine的同步、异步回源方式

解读JVM级别本地缓存Caffeine青出于蓝的要诀2 —— 弄清楚Caffeine的同步、异步回源方式

单服务并发出票实践

单服务并发出票实践

刺激,线程池的一个BUG直接把CPU干到100%了。

刺激,线程池的一个BUG直接把CPU干到100%了。

9
0