我在 Ubuntu 服务器上运行 LAMP 堆栈。今天它两次陷入停顿并需要硬重启。在此之前,它已经稳定了好几个月。自上次更改配置以来已经过去了大约两周,而且这次更改也只是小问题。
翻找一番后,我在系统日志中发现了这一点,几分钟前,一个失败的 cron 电子邮件向我发出了停机警报:
Sep 22 18:14:33 rfb CRON[4912]: (tom) CMD (/usr/share/rfb-scripts/rrdtool-updater.sh)
Sep 22 18:15:40 rfb CRON[4923]: (tom) CMD (/usr/share/rfb-scripts/rrdtool-updater.sh)
Sep 22 18:16:36 rfb CRON[4952]: (tom) CMD (/usr/share/rfb-scripts/rrdtool-updater.sh)
Sep 22 18:16:48 rfb kernel: [16220.076166] apache2 invoked oom-killer: gfp_mask=0x201da, order=0, oom_adj=0
Sep 22 18:16:48 rfb kernel: [16220.076173] Pid: 4908, comm: apache2 Not tainted 2.6.32.9-rscloud #6
Sep 22 18:16:48 rfb kernel: [16220.076175] Call Trace:
Sep 22 18:16:48 rfb kernel: [16220.076186] [<ffffffff8105ca35>] ? T.383+0x78/0x239
Sep 22 18:16:48 rfb kernel: [16220.076191] [<ffffffff8103dea6>] ? timekeeping_get_ns+0xe/0x2e
Sep 22 18:16:48 rfb kernel: [16220.076195] [<ffffffff8105cd2a>] ? __out_of_memory+0x134/0x14b
Sep 22 18:16:48 rfb kernel: [16220.076198] [<ffffffff8105cdab>] ? out_of_memory+0x6a/0x94
Sep 22 18:16:48 rfb kernel: [16220.076202] [<ffffffff8105f96f>] ? __alloc_pages_nodemask+0x47f/0x56b
Sep 22 18:16:48 rfb kernel: [16220.076206] [<ffffffff81061112>] ? __do_page_cache_readahead+0x9e/0x1a1
Sep 22 18:16:48 rfb kernel: [16220.076212] [<ffffffff810384bd>] ? wake_bit_function+0x0/0x2e
Sep 22 18:16:48 rfb kernel: [16220.076214] [<ffffffff81061231>] ? ra_submit+0x1c/0x20
Sep 22 18:16:48 rfb kernel: [16220.076217] [<ffffffff8105af33>] ? filemap_fault+0x17e/0x2ff
Sep 22 18:16:48 rfb kernel: [16220.076221] [<ffffffff8106ea79>] ? __do_fault+0x54/0x335
Sep 22 18:16:48 rfb kernel: [16220.076224] [<ffffffff8106f008>] ? handle_mm_fault+0x2ae/0x636
Sep 22 18:16:48 rfb kernel: [16220.076228] [<ffffffff81014211>] ? do_page_fault+0x299/0x2ae
Sep 22 18:16:48 rfb kernel: [16220.076232] [<ffffffff81226e18>] ? page_fault+0x28/0x30
Sep 22 18:16:48 rfb kernel: [16220.076235] Mem-Info:
Sep 22 18:16:48 rfb kernel: [16220.076237] DMA per-cpu:
Sep 22 18:16:48 rfb kernel: [16220.076238] CPU 0: hi: 0, btch: 1 usd: 0
Sep 22 18:16:48 rfb kernel: [16220.076240] CPU 1: hi: 0, btch: 1 usd: 0
Sep 22 18:16:48 rfb kernel: [16220.076242] CPU 2: hi: 0, btch: 1 usd: 0
Sep 22 18:16:48 rfb kernel: [16220.076244] CPU 3: hi: 0, btch: 1 usd: 0
Sep 22 18:16:48 rfb kernel: [16220.076245] DMA32 per-cpu:
Sep 22 18:16:48 rfb kernel: [16220.076247] CPU 0: hi: 155, btch: 38 usd: 49
Sep 22 18:16:48 rfb kernel: [16220.076249] CPU 1: hi: 155, btch: 38 usd: 37
Sep 22 18:16:48 rfb kernel: [16220.076251] CPU 2: hi: 155, btch: 38 usd: 22
Sep 22 18:16:48 rfb kernel: [16220.076252] CPU 3: hi: 155, btch: 38 usd: 45
前 3 行用于演示正常操作。日志还在继续,但我不会让您感到兴奋。(如果您真的想看就去试试这个Pastebin。
那么我的问题是:我可以使用这个日志来诊断我的问题吗?如果可以,该怎么做?如果有人能告诉我需要做什么来防止这种情况再次发生,那将是一个加分项。
答案1
同意,apache2 是个糟糕的进程,但它以前一直是我的罪魁祸首。通常,尤其是 perl、php 或 mod_python 会不断为某些 Web 应用程序分配内存。随着不同的客户端访问不同的 apache 进程,它们的内存利用率会不断增加。
如果您的流量刚好足以让 Apache 进程保持活动状态,则最终可能会有 256 个 Apache 进程在运行。但是,它不必接近此限制,我曾经遇到过 oom-killer 让我度过了糟糕的一天,因为 30 个 Apache 进程每个使用了 250-300MB 或内存。
增加交换空间会为你赢得一些时间,让你能够进入机器并查看发生了什么,但是你需要得到警告,这样你才能看到哪个进程正在消耗内存,并验证它是否确实是 apache。
在 cron 作业或 cacti 和 snmp 中使用 free 并设置阈值。使用 free,您需要监视缓冲区和可用内存,计算总和并在某些最低阈值时发出警报。
另一件事,如果是 Apache,可能是要增加 MaxClients,它可以有一个较高的默认数字。或者,将 MaxRequestsPerChild 设置为足够低的数字,以便不时地终止进程。这只是一个创可贴,但它可以帮助您坚持足够长的时间来找出问题。
我只是在空中刺了一下 Scott M
答案2
有些东西试图分配比你拥有的更多的内存。你显然可以添加更多的交换,但这会降低你的机器的性能。也许可以添加一些定期运行的小脚本[甚至每分钟运行一次以上]
date >> /some/file
ps faux >> /some/file
并记录输出 - 您可能会发现进程分配了越来越多的内存。
答案3
@user36376 的建议很好。看起来您有内存泄漏。在追踪到泄漏之前,调整 apache 以在处理一定数量的请求后终止进程可能会给您一些时间来识别泄漏。由于这是新出现的,因此应该怀疑是最近的变化。您可能还想考虑使用 ulimit 来最小化 apache 子进程的大小。泄漏的内存很可能可以在影响不大的情况下被换出,因此增加交换可能会有所帮助。
考虑使用 top 来监控虚拟映像大小。您可以更改顺序,使虚拟大小成为第一个排序字段。最大的程序将浮动到顶部。