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


16

我们正在运行一个繁重的Drupal网站,以执行财务建模。考虑到apache使用的内存随着时间的增长而apache进程数保持稳定,我们似乎正在遇到某种内存泄漏:

在此处输入图片说明

在此处输入图片说明

我们知道内存问题来自apache / PHP,因为每当发出a时/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线程分配了一个memory_limit512MB 的PHP ,这说明了内存使用率过高而请求量很少,而max_execution_time120秒的中断时间将终止执行时间较长的线程,因此应避免内存使用率的持续增长。看到。

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

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

附加信息:

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

仅供参考,我们已经意识到交换问题,我们正在单独研究该问题,这与交换开始发生之前观察到的内存泄漏无关。


上一次,当我使用PHP memcached库时,我遇到了LAMP + Drupal严重的内存使用问题。取走后,内存使用量急剧下降。只是一个猜测。稍后可能会为您键入正确的答复。
Janne Pikkarainen 2012年

@JannePikkarainen:我们正在使用PHP memcached库。根据memcache管理页面memcache.php,我们只能看到我们已经分配5GB给了3.3GB正在使用的memcache 。如果您可以在这里进一步协助我们,那就太好了。
2012年

是的,memcached守护进程本身可能还不错。这是PHP内存缓存库,它可能会或可能不会泄漏内存(从而增加Apache进程的内存使用量)。我的问题大约在1-2年前,所以在那之后可能已经解决了。无论如何,如果您不是必须要使用memcached,请尝试将其禁用一会儿,看看Apache内存使用量是否仍在增长。
Janne Pikkarainen 2012年

实际问题是什么?性能差吗?您在告诉我们症状而没有解释我们应该帮助您解决的问题。(您在说这个交换问题是什么?您交换得太多了,这会影响性能吗?)
David Schwartz 2012年

@DavidSchwartz:问题是,如果不重新启动httpd,内存使用量将不断增长,并且由于某些内存不足内核消息而最终崩溃。性能良好(直到内存使用率接近内存限制)。请忽略交换问题。
2012年

Answers:


11

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

不-这仅表示它与网络流量有关。您继续提到,您正在机器上运行mysql-大概是为web服务器管理数据-这很容易成为罪魁祸首。您的Webstack使用的其他服务也可能没有提到。

每个apache线程分配了一个512MB的PHP memory_limit,说明

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

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

并且max_execution_time为120秒,这应该终止执行时间更长的线程

否-仅当执行线程在PHP解释器中时-否则,如果PHP被阻止。

执行财务建模

(叹)

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

我建议您先将mysql移动到单独的计算机上,然后停止使用持久连接(如果您当前正在使用它们)。将内存限制设置低得多,并按脚本覆盖此限制。确保已安装并配置了循环引用垃圾收集器。



1

显然,这就是PHP的工作方式-如果您要进行长循环,即在其中分配对象,并且谁知道是否也通过引用传递对象,那么唯一的处理方法是在每个PHP进程收到N个请求之后阻止它。如果将PHP作为CGI运行,则每个请求都会使其重生-这样就不会发生内存泄漏,并且性能下降可能不会太大。您还可以运行fast-cgi,例如,每1000个请求将php-fcgi进程杀死,并释放其内存-再次没有内存泄漏。如果将PHP作为模块mod_php运行,则可以尝试在httpd.conf中设置maxrequests以查看是否有帮助。我会尝试设置例如10-如果要正常工作,性能下降不会很高,但是应该没有内存泄漏,


-1

检查全局php.ini文件上的内存。不要简单地像1 G等那样贴花valure ...我强烈建议将本地php.ini引入该帐户,以免影响整个服务器。我建议将php.ini的全局限制设置为64M左右,因为对于大多数帐户而言,这通常就足够了

还要检查您的Apache设置

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.