PHP 占用了所有内存

PHP 占用了所有内存

从今天早上开始,我们的一个网络服务器的内存被 php 填满,最终导致服务器开始交换、速度变慢并变得不可用(ssh 登录需要 5 分钟,然后有时会完全死机)...

我想知道您将如何解决此类问题。

Jul 23 06:16:31 websrv2 kernel: [10409040.981882] php-cgi invoked oom-killer: gfp_mask=0x200da, order=0, oom_adj=0
Jul 23 06:16:31 websrv2 kernel: [10409040.981888] php-cgi cpuset=/ mems_allowed=0
Jul 23 06:16:31 websrv2 kernel: [10409040.981892] Pid: 27697, comm: php-cgi Not tainted 2.6.32-5-amd64 #1
Jul 23 06:16:31 websrv2 kernel: [10409040.981894] Call Trace:
Jul 23 06:16:31 websrv2 kernel: [10409040.981903]  [<ffffffff810b6714>] ? oom_kill_process+0x7f/0x23f
Jul 23 06:16:31 websrv2 kernel: [10409040.981908]  [<ffffffff8106bdee>] ? timekeeping_get_ns+0xe/0x2e
Jul 23 06:16:31 websrv2 kernel: [10409040.981912]  [<ffffffff810b6c38>] ? __out_of_memory+0x12a/0x141
Jul 23 06:16:31 websrv2 kernel: [10409040.981916]  [<ffffffff810b6d8f>] ? out_of_memory+0x140/0x172
Jul 23 06:16:31 websrv2 kernel: [10409040.981921]  [<ffffffff810baaf4>] ? __alloc_pages_nodemask+0x4ec/0x5fc
Jul 23 06:16:31 websrv2 kernel: [10409040.981927]  [<ffffffff810d92d8>] ? read_swap_cache_async+0x5d/0xf3
Jul 23 06:16:31 websrv2 kernel: [10409040.981931]  [<ffffffff810d93c5>] ? swapin_readahead+0x57/0x98
Jul 23 06:16:31 websrv2 kernel: [10409040.981937]  [<ffffffff8100c18d>] ? __raw_callee_save_xen_pte_val+0x11/0x1e
Jul 23 06:16:31 websrv2 kernel: [10409040.981941]  [<ffffffff810cd245>] ? handle_mm_fault+0x47f/0x80f
Jul 23 06:16:31 websrv2 kernel: [10409040.981947]  [<ffffffff813001a6>] ? do_page_fault+0x2e0/0x2fc
Jul 23 06:16:31 websrv2 kernel: [10409040.981952]  [<ffffffff812fe045>] ? page_fault+0x25/0x30
Jul 23 06:16:31 websrv2 kernel: [10409040.981954] Mem-Info:

我尝试按照内存使用情况对进程进行排序:

ps -e -orss=,args=|sort -b -k1,1n|pr -TW$COLUMNS

我看到很多 /usr/bin/php-cgi 消耗内存。如何限制 PHP 的总体内存消耗,以便服务器不会达到极限而耗尽所有内存/交换空间并变得不可用?

更多系统信息:

ii  php5                                5.3.3-7+squeeze18            server-side, HTML-embedded scripting language (metapackage)
ii  apache2                             2.2.16-6+squeeze11           Apache HTTP Server metapackage

答案1

您可以使用 cgroups 限制用户(运行 php-cgi 进程的用户)的内存使用量。

例如,要限制用户的内存使用量,您可以执行以下操作:

# file: /etc/cgconfig.conf
group php {
    memory {
        memory.limit_in_bytes = "2G";
    }
}

然后你必须将你的 php-cgi 用户添加到这个 cgroup-group:

# file: /etc/cgrules.conf
phpcgiuser   memory   php

如果您想限制每个进程的内存使用量,可以使用 ulimit(每个进程 100 MB)来实现。

# file: /etc/security/limits.conf
phpcgiuser  hard  as   102400

编辑:尽管如此,您还是应该分析导致内存泄漏的软件。

答案2

如果这是经常使用的结果,您应该检查这些 PHP 脚本是否存在内存泄漏、无限循环和此类可怕的问题。

答案3

你用的是什么操作系统?我在所有网络服务器上为所有网络应用程序提供服务时,所做的是:

  • 我为每个单独的 Web 应用程序创建单独的池。
  • 我在 php.ini 中限制了它们可以吸收的内存量(memory_limit = 2048M)
  • 我已经修改了所有池,以便运行 Web 服务器的 NginX 用户实际上也运行 PHP 池。

通过这种方式,我从来没有遇到过你现在遇到的情况,因为每次我有一个应用程序试图用它自己溢出 RAM 时,它都会被踢出,而不会对其余的 Web 应用程序产生任何影响。

然而,我也强烈建议找到这次大规模溢出的罪魁祸首,它可能是一次攻击,也可能是一段编写错误的代码(我认为是第二种)。

但我最推荐的是升级你的 PHP 版本!!!! PHP 5.5 已经过时了,不再提供任何支持。如果无法升级到 7.1,那么至少升级到 5.6。

相关内容