我的设置:我有 3 台几乎相同的 Web 服务器,它们通过 DNS 进行简单的负载平衡,为同一个高负载动态网站提供服务。该服务已使用相同的 apache 配置运行了两年多:apache2、php5、ubuntu 8.04 linux 2.6.24-29-server。
我的问题:大约两周前,我遇到了此配置的问题。几乎每天我都会遇到大约 5 分钟的短暂时间,在此期间网站无法访问。我仍然能够通过 ssh 登录服务器。如果我运行htop
,我会看到机器什么也没做。我大约有 1000 个 apache 进程在运行,但没有 CPU 活动。
我使用 apache mod_status 来调试这种情况。进程记分板如下所示:
_C.___K_______________________R._______.__K_K____K___C_______.__
_______C__________.___________________________________.________C
_.____K__________K___K_WK_____._K_____________________________._
W______K__________K________.____________________._______C_______
_C_.__K__K____.._.._____________________________________C_______
_R___________K___.______C________.C_________.______._____C______
____________KKC____K_____K__WC_________________C_____.__.____.__
_____________________C_________K______.____C______._____________
_.___C____.___.___________________________.K______.____K________
W__.___________________C.__.____K________K_______R_._.__._______
__C__C_.__________C__C_______._____W______________C_.___C_______
____.______C_____________C________.____C____________.________._K
__.__________.K_____________K_________._____C____.K__________KW_
__K.W________R_________._______.___W___________.____.__K_____W__
W___.___..________W____K
Scoreboard Key:
"_" Waiting for Connection, "S" Starting up, "R" Reading Request,
"W" Sending Reply, "K" Keepalive (read), "D" DNS Lookup,
"C" Closing connection, "L" Logging, "G" Gracefully finishing,
"I" Idle cleanup of worker, "." Open slot with no current process
因此,大多数进程都在等待连接。大约 5 分钟后,情况将恢复正常:每台机器上都有许多最少的进程,大多数工作者都有“。”状态(意味着它们可以处理请求),当然网站是可以访问的!
所以我尝试在日志中查找一些东西,但根本什么都没有...apache 访问日志大约有 4 分钟没有动静,错误日志也是如此。我在其他系统日志中也找不到任何错误。
所有 3 个网络服务器的情况都相同(它们同时都具有此负载峰值和无响应情况),因此我认为这与硬件无关。但我认为,这可能与某些网络(tcp)问题有关。
有任何想法吗?
编辑:我刚刚发现的更多信息:
它刚刚再次发生了,并且我能够验证当此问题发生时我也无法进行本地连接。
事情发生后,我使用以下命令做了一些连接统计:netstat -an|awk '/tcp/ {print $6}'|sort|uniq -c
- 109 关闭_等待
- 2652 成立
- 2 FIN_WAIT1
- 11 最后确认
- 12 聆听
- 91 SYN_RECV
- 1 SYN_SENT
- 16 等待时间
如果我稍后执行相同的命令,我会看到如下结果:
- 4 结束语
- 108 已建立
- 18 FIN_WAIT1
- 182 FIN_WAIT2
- 37 最后确认
- 12 聆听
- 50 SYN_RECV
- 11276 时间等待
因此,在正常情况下,此时 apache 处理的客户端打开的连接只有 100-200 个。当我遇到此“崩溃”时,我的连接数会多得多。分析此问题的最佳方法是什么?
EDIT2:apache2.conf 中的重要行是:
KeepAlive On
MaxKeepAliveRequests 20
KeepAliveTimeout 1
<IfModule mpm_prefork_module>
ServerLimit 920
StartServers 30
MinSpareServers 80
MaxSpareServers 120
MaxClients 920
MaxRequestsPerChild 700
</IfModule>
它是带有 php_mod 的 apache2 prefork。
该服务器有 8GB 内存和 4GB 交换分区。
答案1
您应该启用 mod_status 的扩展状态(http://httpd.apache.org/docs/2.2/mod/mod_status.html#extendedstatus) 来监控当前主机和正在处理的请求。我认为有一个脚本/页面花费了太多时间来释放连接,这导致连接堆积。
答案2
首先:检查Max open files
进程的限制。活动套接字连接计为打开的文件。cat /proc/###/limits
是检查另一个进程的有效值的好方法。您可以使用 ### 获得打开文件的列表,其中lsof -p ###
### 是您的 Web 服务器的进程 ID。您可以比较一下,lsof -p ### | wc -l
看看距离限制有多近。如果达到限制,您还应该在 apache 的 error_log 中看到消息。
您需要为每个套接字连接以及每个 cgi 脚本或数据文件引用设置一个文件句柄。对于 920 MaxClients,您应该为 httpd 进程配置至少 4,000 个文件。您可以通过在 /etc/security/limits.d/ 中添加包含以下内容的文件来增加文件数量。确保用户名与您用于 Web 服务器的用户名相匹配。
apache soft nofile 10000
apache hard nofile 10000
第二:如果端口耗尽是您的问题,您可以调整 /etc/sysctl.conf 中的某些 ip 设置。(以 开头)。这通常只在存在大量非常小的连接时才会出现问题。许多 TIME_WAIT 套接字就是这种情况的一个指标,但只有当系统日志中出现有关和net.ipv4.tcp_fin_timeout
的错误时,这才表示端口耗尽。您还应确保您的服务器位于可以阻止恶意 SYN 攻击的防火墙后面。possible SYN flooding
Sending cookies
答案3
另外,请记住,在 prefork MPM 中,每个进程的内存空间中都会有 PHP(其内存限制设置是什么?)。您可能想尝试更改为 worker MPM,这可能需要略有不同的 PHP 模块。
远程耳环也值得修剪Apache配置中多余的模块
根据我的经验,此类事件是由搜索引擎爬虫或 ARP 冲突等事件触发的。或者是网络相关部分的流量水平。
您可能会发现“sar”很有用......虽然不是最友好的,但肯定有用。
可能还与 io 有关。Sar 可以告诉您(如果您将其配置为记录磁盘活动)平均 io 等待时间是多少。您还可以查看 top 中的 IO 等待时间(这是一个百分比,请阅读它的实际含义)。如果您使用的是 SAN 或虚拟环境,这可能很重要。