希望有人能给我指明正确的方向,因为我花了一周的时间试图找出“问题”在哪里,但却没能成功,尝试过将问题发布到 Apache 用户邮件列表,但也想在这里将其回复。
在 CentOS 5.8 上运行 Apache 2.2.3 mod_php。
同时,每天当流量很大时,我们都会遇到 Apache 不再响应任何 HTTP 请求的问题。
这听起来像是达到标准 MaxClients 的问题,但事实似乎并非如此。
此外,在此期间登录机器时平均负载低于 1,并且仍有足够的可用 RAM。
查看 /var/log/httpd/error_log 我注意到以下模式:
[Mon Apr 30 07:00:34 2012] [info] server seems busy, (you may need to increaseStartServers, or Min/MaxSpareServers), spawning 32 children, there are 0 idle, and 905 total children
[Mon Apr 30 07:00:35 2012] [info] server seems busy, (you may need to increase StartServers, or Min/MaxSpareServers), spawning 32 children, there are 0 idle, and 937 total children
[Mon Apr 30 07:00:36 2012] [info] server seems busy, (you may need to increase StartServers, or Min/MaxSpareServers), spawning 32 children, there are 0 idle, and 969 total children
[Mon Apr 30 07:00:37 2012] [info] server seems busy, (you may need to increase StartServers, or Min/MaxSpareServers), spawning 32 children, there are 35 idle, and 1001 total children
[Mon Apr 30 07:00:42 2012] [debug] mpm_common.c(663): (70007)The timeout specified has expired: connect to listener on [::]:80 <br>
[Mon Apr 30 07:00:49 2012] [debug] mpm_common.c(663): (70007)The timeout specified has expired: connect to listener on [::]:80 <br>
[Mon Apr 30 07:00:56 2012] [debug] mpm_common.c(663): (70007)The timeout specified has expired: connect to listener on [::]:80 <br>
[Mon Apr 30 07:01:03 2012] [debug] mpm_common.c(663): (70007)The timeout specified has expired: connect to listener on [::]:80 <br>
每天几次,就在1000 total children
Apache 停止响应并且必须重新启动才能再次工作之后。
我查看了几周前的 error_log,它是相同的模式,服务器总共达到 1000 个子进程,然后立即吐出
[debug] mpm_common.c(663): (70007)The timeout specified has expired: connect to listener on [::]:80
错误消息并停止响应。
但是服务器上的负载很低...即使我尝试请求一个简单的 index.html 文件它也会超时。
以下是配置中的相关部分:
Timeout 45
KeepAlive On
MaxKeepAliveRequests 10000
KeepAliveTimeout 3
<IfModule prefork.c>
StartServers 80
MinSpareServers 50
MaxSpareServers 120
ServerLimit 3500
MaxClients 3500
MaxRequestsPerChild 2000
</IfModule>
有人知道为什么 Apache 在停止处理更多请求之前能够达到的神奇子数是 1000 吗?
或者如何理解这个(70007)The timeout specified has expired: connect to listener on [::]:80
信息?
它指的是什么“指定超时”?
我仔细检查了 Max Open Files,之前是 1024,但现在是 16384,仍然是同样的问题。
答案1
虽然可能性不大,但我遇到过类似的问题。我不记得具体是什么错误消息,但问题的原因一直是 PHP 程序存在错误,导致递归请求(即程序请求一个 URL,然后又重新请求同一个 URL 等)。例如,我在ErrorDocument
设置中看到过这种情况,其中应该处理错误的文档存在错误或不存在,从而触发了错误。
您可以轻松地在 access.log 中验证这是否是问题所在:您应该会在很短的时间内收到大量来自服务器 IP 地址的请求。这一直有效,直到您达到 MaxClients 设置或系统资源耗尽。唯一的解决办法是修复有问题的 PHP 程序。
答案2
Timeout 45
我相信它指的是这个超时。可能是某些东西打开了连接,然后什么也没做(即客户端在打开连接后没有发送任何内容,或者您的脚本在将数据写入客户端后没有关闭连接),Apache 等待 45 秒后才放弃。然后它关闭连接。您可以降低这个值,这样 Apache 就可以更快地超时无效连接尝试,但更好的解决方案是首先尝试确定为什么会发生这种情况。
http://httpd.apache.org/docs/2.1/mod/core.html#timeout
也许还请查看此页面以了解一般的性能问题?
答案3
检查 Apache 的 KeepAlive 是否已打开以及 KeepAliveTimeout 的值是多少。它实际上不应超过 3 秒。它将保留分配给客户端的特定进程/线程。
然后在 httpd 的 conf 目录中查找 1000,看看这个数字是否在某处设置。
grep -r '1000' /etc/httpd/conf
grep -r '1000' /etc/httpd/conf.d
除此之外,还可能存在这样的情况:您的 php 代码(错误地)让处理它的每个进程/线程无限期地保持活动状态,而您已经用完了它们。