Apache:孤立的 fcgi php 进程

Apache:孤立的 fcgi php 进程

我们有一个装有 apache 2.2.14、PHP 5.3.2 的网络服务器。

PHP 使用 mod_fcgid 执行(见底部)。一切正常,但有时,我们仍需弄清楚是什么触发了这种情况,当 php 进程“轮换”时,它们仍处于活动状态且处于孤立状态:apache 会产生新的 php 进程,而旧进程仍保留在系统中。终止它们并不总能将它们踢走。更有可能的是,“apache2ctl graceful”会将系统从这些过时的进程中释放出来。我们在错误日志中发现了这一点:[2013 年 6 月 18 日星期二 20:49:54] [警告] mod_fcgid:进程 2009 graceful kill 失败,根据我搜索的结果,发送 SIGKILL 是相当正常的,但这就是我在其中一个进程泄漏期间在 apache 日志中发现的全部内容。

幸运的是,这种情况很少发生,通常 apache 和 php 运行正常,在 fcgid 子代更新期间不会出现问题。我们如何了解这些情况下出了什么问题?

站点中的 mod_fcgid 配置:

<IfModule mod_fcgid.c>
SuexecUserGroup domain domain
<Directory /var/www/fomain.it/htdocs/>
AddHandler fcgid-script .php
FCGIWrapper /var/www/fcgi/domain.it/fcgi-starter-php .php
Options +ExecCGI -Indexes
AllowOverride FileInfo Options
Order allow,deny
Allow from all
</Directory>
<Directory /var/www/fcgi/domain.it/>
AllowOverride None
Options +ExecCGI MultiViews -Indexes
Order allow,deny
Allow from all
</Directory>
</IfModule>

/var/www/fcgi/domain.it/fcgi-starter-php:

#!/bin/sh

PHPRC=/var/www/fcgi/domain.it/php/

export PHPRC
PHP_FCGI_CHILDREN=8
export PHP_FCGI_CHILDREN
PHP_FCGI_MAX_REQUESTS=5000
export PHP_FCGI_MAX_REQUESTS

exec /usr/lib/cgi-bin/php $1

我们目前找到了一种避免服务器充满孤立进程的解决方法。您可以使用以下方法摆脱陈旧的进程:

apache2ctl graceful

并使用以下命令终止这些进程:

pkill -f -x /usr/lib/cgi-bin/php -P 1

编写脚本并安排这两个命令(经过适当的检查)将避免服务器承载大量无用的进程,但问题仍然存在。

答案1

我遇到了类似的问题,即 fcgid 在一段时间的活动之后用尽了可用的进程槽。

日志信息大致如下:

[fcgid:warn] mod_fcgid: can't apply process slot for /var/www/cgi-bin/xxx/php-cgi, referer: ...

我追踪问题到此为止:

[fcgid:emerg] (35)Resource deadlock avoided: [client ....] mod_fcgid: can't get pipe mutex, referer: ...

这是由于锁定不当造成的。在我的例子中,Apache 使用 fcntl() 锁定(在 Debian 上是默认的),因此我将其更改为 flock() apache2.conf

Mutex flock:${APACHE_LOCK_DIR} default

引导我找到解决方案的参考资料: https://bz.apache.org/bugzilla/show_bug.cgi?id=53999

关于各种锁定选项的文档(fcgid 有一个警告,建议不要将其用于涉及线程的任何操作): https://httpd.apache.org/docs/2.4/mod/core.html#mutex

答案2

我没有真正的答案,但也许更多的信息可以帮助解决问题。我想说的是,我在使用 PHP 5.3.5 的 Windows 服务器上遇到了同样的问题。

一些 cgi 进程在完成实际执行后仍保留为一种僵尸任务。它们甚至会忽略 max_execution time 等设置。

目前我有一个计划脚本可以终止这些旧进程。该解决方案的问题是,即使“正常”的 cgi 进程也被终止了,检测进程的运行时间并仅在它们的 max_execution 时间已过时才终止它们可能会很有用。

答案3

按照 Thomas 的建议改为“sem”https://bz.apache.org/bugzilla/show_bug.cgi?id=53999对我有用。

因此我建议任何人都编辑他的 apache2.conf,注释掉 Mutex 行,并输入:

# Mutex file:${APACHE_LOCK_DIR} default   # Original debian config
Mutex sem  # Solves orphaned PHP processes.

相关内容