许多长 运行 Apache 进程在一段时间后没有请求就处于 READ 状态

To many long running Apache processes in READ status without requests after a certain time

我正在使用 /server-status 来监视 Apache 进程。开始时它们看起来像这样:

_____W_K__K____________C_K________C_____________W_..............
................................................................
................................................................

但是 运行ning 几个小时后看起来像这样:

R_KCR___KR__RKRR_RRRKRRRRRRKRR_RRCK____R_RRRR_RRRKRRRKRRRRRRRRR_
R_RRRR_R.RR.R_R.R_R..CKRRRRW.K_RCRKRR_R_.._R._.RK_KRK_.RRR.KK_.R
..RR............................................................

太多"Read"(R) status 花了很长时间,我不知道他们是做什么的,因为他们连request都没有。 (请注意,我从上面的示例中跳过了额外的“.”状态,我总共有 2000 个可用位置。)在进程列表中,我有大约 40 "R" 个进程,如下所示:

Srv  PID   Acc        M CPU  SS   Req Conn Child Slot   Client       VHost Request
15-2 21291 0/37/11158 R 0.03 7468 2   0.0  1.93  198.35 82.78.95.105

报告的 header 看起来像这样:

Server Version: Apache/2.4.10 (Debian) mod_fcgid/2.3.9 OpenSSL/1.0.1t
Server MPM: prefork
Server Built: Sep 15 2016 20:44:43
Current Time: Thursday, 12-Jan-2017 08:38:46 EET
Restart Time: Wednesday, 11-Jan-2017 00:51:18 EET
Parent Server Config. Generation: 3
Parent Server MPM Generation: 2
Server uptime: 1 day 7 hours 47 minutes 27 seconds
Server load: 0.34 0.35 0.39
Total accesses: 1599556 - Total Traffic: 29.9 GB
CPU Usage: u18.87 s6.81 cu0 cs0 - .0224% CPU load
14 requests/sec - 274.0 kB/second - 19.6 kB/request
90 requests currently being processed, 27 idle workers

我有一台私人服务器:4X3.6GHZ Xeon 处理器,2X512 GB SSD,32 GB 内存,Debian 3.16.36-1,Apache 2.4.10,PHP 5.6.29,mod_fcgid, php-fpm, php5-cgi, prefork.

我的一些 apache2.conf 设置:

Timeout 14400
KeepAlive On
MaxKeepAliveRequests 1000
KeepAliveTimeout 3
HostnameLookups Off

我的 mpm_prefork.conf 设置:

<IfModule mpm_prefork_module>
  StartServers 50
  MinSpareServers 25
  MaxSpareServers 50
  ServerLimit 2000
  MaxRequestWorkers 2000
  MaxConnectionsPerChild 1000
</IfModule>

我的一些 fcgid.conf 设置:

FcgidMaxRequestLen 1073741824
FcgidOutputBufferSize 1073741824
FcgidMaxProcesses 200
FcgidMaxProcessesPerClass 100
FcgidMinProcessesPerClass 0
FcgidProcessLifeTime 30
FcgidConnectTimeout 30
FcgidIOTimeout 14400
FcgidBusyTimeout 14400
FcgidIdleTimeout 3
FcgidIdleScanInterval 1

我在服务器中有一些长时间的 运行ing cronjobs,这就是为什么我需要在 Apache 和 PHP 进程上的大“14400”(=4 小时)超时。

问题:

  1. 为什么有这么多 "R" 状态没有请求?
  2. 他们做什么,我怎么知道?
  3. 为什么他们 运行 这么久?

更新一:

A 已将超时修改为 7200(=2 小时),这是我可以 运行 我的 cronjobs 的最小值。但是我的 cronjobs 没有问题。

FcgidIOTimeout 7200
FcgidBusyTimeout 7200

也适用于 Apache:

Timeout 7200

基于我这样做了:

FcgidOutputBufferSize 0

基于mod_fcgid: ap_pass_brigade failed in handle_request function我这样做了:

FcgidMaxRequestsPerProcess 500

几个小时后服务器停止响应:

Service Unavailable: The server is temporarily unable to service your request due to maintanance downtime or capacity problems. Please try again later.

在日志中我发现了一些像下面两个这样的错误:

[fcgid:warn] (104)Connection reset by peer: mod_fcgid: ap_pass_brigade failed in handle_request_ipc function
[fcgid:warn] (32)Broken pipe: mod_fcgid: ap_pass_brigade failed in handle_request_ipc function

还有一堆这样的(可能针对每个请求):

[fcgid:warn] mod_fcgid: too much processes, please increase FCGID_MAX_APPLICATION

问题二:

  1. 这些错误是什么意思?我该如何更正它们?
  2. 为什么服务器停止响应?可能是因为错误...
  3. mod_fcgid、php-fpm、php5-cgi、prefork 模块是否完全兼容且有效?这是我拿到新服务器时的默认配置。

问题已解决。

解决方案是将 Apache 的 Timeout 值降低到 15 这样的数字。我意识到 运行 一个长的 PHP 脚本(甚至几个小时)不需要这个超时要高,PHP 的 max_execution_time 足够大就足够了。

更新

我还升级到 PHP 7.1,在 PHP-FPM 下使用 FastCGI,并且我按照 esra-s 的建议将 Apache 的 MPM 模式更改为事件,它运行得非常糟糕。非常感谢!