PHP 和 mod_fcgid:ap_pass_brigade 在 handle_request_ipc 函数中失败

PHP and mod_fcgid: ap_pass_brigade failed in handle_request_ipc function

这在 之前已被询问和回答,但是那里的解决方案对我不起作用。

mod_fcgid 配置

<IfModule mod_fcgid.c>
  AddHandler    fcgid-script .fcgi
  FcgidIPCDir /var/run/mod_fcgid/
  FcgidProcessTableFile /var/run/mod_fcgid/fcgid_shm

  FcgidIdleTimeout 60
  FcgidProcessLifeTime 120
  FcgidMaxRequestsPerProcess 500
  FcgidMaxProcesses 150
  FcgidMaxProcessesPerClass 144
  FcgidMinProcessesPerClass 0
  FcgidConnectTimeout 30
  FcgidIOTimeout 600
  FcgidIdleScanInterval 10
  FcgidMaxRequestLen 269484032

</IfModule>

php-cgi脚本

#!/bin/bassh
export PHPRC=/var/www/vhosts/example.com/etc/
export PHP_FCGI_MAX_REQUESTS=5000
exec /usr/bin/php-cgi

系统详情

所以我的 FcgidMaxRequestsPerProcess 设置为 500,我的 PHP_FCGI_MAX_REQUESTS 设置为 10 倍,如之前的答案和 Apache 文档中所建议的那样。但是我仍然遇到这些错误

[Thu Nov 19 18:16:48.197238 2015] [fcgid:warn] [pid 6468:tid 139726677858048]
(32)Broken pipe: [client X.X.X.X:41098] mod_fcgid: ap_pass_brigade failed in handle_request_ipc function

大约一年前我也遇到了同样的问题,然后我尝试了很多事情,最后我做了一些成功的事情和 运行 在阅读文档后我的问题消失了。首先重要的事情需要设置为:

FcgidBusyTimeout     300 [default]
FcgidBusyScanInterval    120 [default]

该指令的目的是终止挂起的应用程序。对于可能需要更长时间来处理请求的应用程序,可能需要增加默认超时。因为检查是以 FcgidBusyScanInterval 定义的时间间隔执行的,请求处理可能会被允许进行更长的时间

FcgidProcessLifeTime     3600 [default]

如果 class 的进程数超过 FcgidMinProcessesPerClass.

,则存在时间超过此时间的空闲应用程序进程将被终止

此进程生命周期检查以配置的频率执行 FcgidIdleScanInterval

FcgidZombieScanInterval   3 [seconds default]

模块会在此时间间隔检查退出的 FastCGI 应用程序。在这段时间里,应用程序可能作为僵尸存在于进程table中(在Unix上)。

注意:以上所有选项根据您的申请过程时间或需要减少或增加或适用于特定的虚拟主机。

但是我的问题可以通过这个选项解决:

以上选项已经调整了我的服务器,但一段时间后错误似乎又出现了,但这个错误真的解决了:

 FcgidOutputBufferSize   65536 [default]

我已经改成了

 FcgidOutputBufferSize   0

这是模块在将数据刷新到客户端之前将从 FastCGI 应用程序读取的最大响应数据量。这将立即刷新数据,而不是等待 64KB 的字节,这确实帮助我更快地刷新进程。

我遇到的其他问题

if 500 来自 Nginx 超时的错误。修复:

/etc/nginx/nginx.conf

keepalive_timeout  125;
proxy_read_timeout 125;
proxy_connect_timeout 125;
fastcgi_read_timeout 125;

我会间歇性地收到 MySQL "MySQL server has gone away" 错误,这需要再进行一次调整: /etc/my.conf

wait_timeout = 120

然后,为了好玩,我继续提高了我的 PHP 内存限制,以防万一: /etc/php.ini

memory_limit = 256M

使用 SuExec

mod_fastcgiSuExecApache 2.x 下根本不起作用。我只遇到了麻烦(在我们的测试中它还有许多其他问题)。问题的真正原因是 SuExec

在我的情况下,这对我来说是一个初创公司,我启动 Apache,mod_fcgid 为每个虚拟主机生成了 5 个进程。现在,当使用一个简单的上传脚本并提交一个大于 4-8KB 的文件时,对于执行脚本的特定虚拟主机,所有这些子进程都会立即被终止。

可能会在 mod_fcgid 中进行调试构建或启动登录,这可能会提供线索。

我同时尝试了 mod_fastcgi 一年,我也可以和许多其他人一起说 SuExec 只是麻烦而且 运行 一点也不顺利,在每种情况下。

该警告与任何 Fcgidxxx 选项无关,只是由于客户端在服务器有机会响应之前关闭了他们的连接端。

来自实际来源:

/* Now pass any remaining response body data to output filters */
if ((rv = ap_pass_brigade(r->output_filters, brigade_stdout)) != APR_SUCCESS) {
    if (!APR_STATUS_IS_ECONNABORTED(rv)) {
        ap_log_rerror(APLOG_MARK, APLOG_WARNING, rv, r,
                      "mod_fcgid: ap_pass_brigade failed in "
                      "handle_request_ipc function");
    }

    return HTTP_INTERNAL_SERVER_ERROR;
}

感谢 Avian's Blog 发现了它。

当网站使用异步请求时,可能会发生此错误。这些不会直接在网页上显示为错误结果,但会触发 PHP 脚本的执行。如果此类脚本在执行期间失败并且没有 return 结果,则会记录此错误或类似的奇怪错误。您需要做的是识别对 PHP 脚本的 JavaScript (AJAX) 调用,并找出这些脚本执行失败的原因。

在等待服务器响应之前关闭连接的客户端。客户端确实正在关闭它,但它确实这样做了,因为它没有收到来自 AJAX 调用的响应,这也是由网站的错误脚本引起的。