如何调查 Apache 和 PHP 的内存泄漏?

如何调查 Apache 和 PHP 的内存泄漏?

我们正在运行一个执行财务建模的大型 Drupal 网站。我们似乎遇到了某种内存泄漏,因为随着时间的推移,apache 使用的内存不断增加,而 apache 进程的数量保持稳定:

在此处输入图片描述

在此处输入图片描述

我们知道内存问题来自 apache/PHP,因为每当我们发出时/etc/init.d/httpd reload内存使用量就会下降(参见上面的屏幕截图和下面的 CLI 输出):

在 httpd 重新加载之前

$ 免费
             已使用的、可用的、缓存的共享缓冲区总数
内存:49447692 45926468 3521224 0 191100 22609728
-/+ 缓冲区/缓存:23125640 26322052
交换:2097144 536552 1560592

httpd 重新加载后

$ 免费
             已使用的、可用的、缓存的共享缓冲区总数
内存:49447692 28905752 20541940 0 191360 22598428
-/+ 缓冲区/缓存:6115964 43331728
交换:2097144 536552 1560592

每个 apache 线程都分配有 512MB 的 PHP,memory_limit这解释了在请求量低的情况下内存使用量为何如此之高,而max_execution_time120 秒的等待时间应该终止执行时间较长的线程,因此应该可以防止我们看到的内存使用量持续增长。

问:我们如何调查导致内存泄漏的原因?

理想情况下,我正在寻找可以在系统上执行的故障排除步骤,而不必打扰开发团队。

附加信息:

OS: RHEL 5.6
PHP: 5.3
Drupal: 6.x
MySQL: 5.6

仅供参考,我们知道交换问题,我们正在单独调查,并且与我们在交换开始发生之前观察到的内存泄漏无关。

答案1

我们知道内存问题来自 apache/PHP,因为每当我们发出 /etc/init.d/httpd reload 时,内存使用量就会下降

不 - 这只意味着它与网络流量有关。您接着提到您在机器上运行 mysql - 大概是管理网络服务器的数据 - 它很可能是罪魁祸首。您的 webstack 使用的其他服务也可能是罪魁祸首,但您没有提到。

每个 Apache 线程分配的 PHP memory_limit 为 512MB,这解释了

不,不是。您报告的平均繁忙服务器数为 7,最大繁忙服务器数为 25 - 但您的内存图显示增量约为 25Gb。

实际上,您应该重新开始基本的 HTTP 调整 - 您似乎正在运行恒定的 256 个 httpds,但您的峰值使用量是 25 - 这简直是愚蠢的。

并且 max_execution_time 为 120 秒,这将终止执行时间较长的线程

否 - 仅当执行线程在 PHP 解释器内时才会发生 - 如果 PHP 被阻止则不会发生。

执行财务建模

(叹)

如果您能提供有关如何配置 Apache、线程或 prefork、版本、如何调用 PHP(模块、cgi、fastcgi)、是否使用持久连接、是否使用存储过程的详细信息,那将会很有帮助。

我建议你首先将 mysql 移到单独的机器上,并停止使用持久连接(如果你目前正在使用它们)。设置内存限制很多降低并根据每个脚本覆盖此限制。确保已安装并配置了循环引用垃圾收集器。

答案2

现在你可能已经解决了你的问题。为了防止服务器交换/抖动,我每小时从 cron 运行以下命令:

#!/bin/sh 
sync; echo 3 > /proc/sys/vm/drop_caches

我并不是说这是一个解决方案,而只是一种在调查内存泄漏的实际原因时保持系统运行并尽量减少停机时间的方法。

更多详情可在这找到。

http://www.tecmint.com/clear-ram-memory-cache-buffer-and-swap-space-on-linux/

答案3

显然,这是 PHP 的工作方式 - 如果您正在执行分配对象的长循环,谁知道您是否也通过引用传递它们,那么处理它的唯一方法是在每个 PHP 进程发出 N 次请求后停止它。如果您将 PHP 作为 CGI 运行,则每个请求都会使其重生 - 因此不会出现内存泄漏,性能下降可能不会那么大。您还可以运行 fast-cgi,例如每 1000 个请求,php-fcgi 进程就会被终止并释放内存 - 同样不会出现内存泄漏。如果您将 PHP 作为模块 mod_php 运行,您可以尝试在 httpd.conf 中设置 maxrequests 以查看是否有帮助。我会尝试设置例如 10 - 如果它能工作,性能下降不会很高,但不应该有内存泄漏,即使在所有 250 个 httpds 都在使用的情况下出现高峰(10*250 = 2500 - 每 10MB 内存使用量为 25GB - 所以如果你没有 128GB RAM,也可以尝试将 httpd 进程数降低到例如 50)。

答案4

检查全局 php.ini 文件的内存。不要简单地将其值设为 1 G 等...我强烈建议将本地 php.ini 引入该帐户,以免影响整个服务器。我建议将全局 php.ini 限制设置为大约 64M,因为这通常足以满足大多数帐户的需求

检查你的 apache 设置

相关内容