Apache MaxClients 已达到上限,服务器无响应,即使在非高峰期也是如此

Apache MaxClients 已达到上限,服务器无响应,即使在非高峰期也是如此

我们有一个 Apache 服务器,几乎每天都会变得没有响应。通过检查 /server-status (mod_status),我们可以看到有 60 个子进程都处于“W”(发送回复)状态。

  1. 如果我们运行,service httpd restart一切都会恢复正常,问题也会在一天左右的时间内消失。
  2. 如果我们不重新启动 Apache 而是杀死每个子进程,问题仍然存在(这是我们访问 /server-status 的唯一方法,它会响应直到所有进程都进入“W”状态)。
  3. 对我来说,当问题开始发生时,我们的 PHP 脚本似乎从未完成,这让我认为这是一个 MySQL、Solr 或 PHP/Apache 超时问题。
  4. 然而...
    • Solr/MySQL 立即响应。
    • 有大量可用的 MySQL 连接(我们使用 AWS-RDS,允许的最大连接数大于 Apache 进程数)。
    • RAM 仍然可以使用(每个进程为 10m x 60 = 600Mb RAM,还有足够的可用空间)。
    • PHP 已max_exectution_time设置为“30”。
    • ApacheTimeOut设置为“60”。
    • 我们不使用持久的 MySQL 连接。
    • 我们用于curl_setopt($conn, CURLOPT_FORBID_REUSE, 0)查询 Solr (我希望如果连接断开,curl 能够正确地收集垃圾)。
  5. 但似乎许多过程绝不完成...我让一个进程继续运行,同时终止所有其他进程,并且该进程持续了 2 个小时,仍然提供完全相同的页面(我可以在 /server-status 中看到这一点),通常需要 50 毫秒才能响应。
  6. 我们的代码中不使用set_time_limit(0)任何类似的愚蠢的东西。
  7. 我认为省略set_time_limit意味着脚本将在之后完成max_execution_time

我有一个理论,Apache 的ListenBacklog设置太高了,每当我们终止进程时,就会立即启动 60 个新进程,所有进程都试图响应早已消失的客户端。这可以解释为什么我们重新启动服务器后问题就消失了。但似乎ListenBacklog没有设置,因此将使用默认值“511”。我尝试连续多次终止所有子进程以清除积压,但问题仍然存在……对 PHP 页面的所有新请求都需要很长时间才能响应(大多数都没有响应)。

PHP配置:

max_execution_time = 30
max_input_time = 60
safe_mode = off

Apache 配置:

KeepAlive off

<IfModule prefork.c>
StartServers       8
MinSpareServers    5
MaxSpareServers   20
ServerLimit      256
MaxClients       60
MaxRequestsPerChild  1000
</IfModule>

我已经没有主意了...如能提供任何提示我将非常感激!

答案1

我建议的故障排除步骤是:

  • strace -p $PID在一个挂起的进程上查看它被卡在了哪些系统调用上(如果有的话)
  • lsof -p $PID查看该进程中打开的文件句柄或套接字是否可以给你提供线索
  • tcpdump -vv -A -s1500 port 80查看流量情况以及响应哪里出了问题。

相关内容