我们的 SOAP Web 服务器在 CentOS 上的 Apache 上使用 PHP 运行,大量使用 MySQL。服务器需求很大 - 大多数请求都很小,只涉及两三个 MySQL 查询,但请求数量非常多 - 高峰时段每秒可能有几百个查询。每个请求的数据流量通常小于 1Kb,通常只有几个字节。
运行该程序的硬件相当不错,有 18 个内核和 32 GB 的 RAM,而且通常运行良好。CPU 使用率从未超过 30%,物理 RAM 消耗从未超过 50%。但是,服务器偶尔会停滞,Apache 会卡住。这种情况可能会持续大约一分钟,然后再次恢复正常服务。
我对此进行了深入分析,以了解在停顿期间发生了什么。Apache 的连接数已达到最大值,几乎所有连接都处于“读取”状态。CPU 使用率降至几乎为零,内存使用率没有变化,网络和磁盘 IO 都急剧下降,因此看起来系统完全处于空闲状态。
在谷歌上搜索了很多次后,我确信这可能与某些超时设置有关 - 网络连接释放得不够快,Apache 耗尽了。这可以解释为什么 Apache 会在一段时间后恢复正常运行,它会等待所有连接超时,然后继续运行。执行“netstat -an”可以支持这一点,因为我确实看到很多连接处于 TIME_WAIT 状态。但是,我已减少 Apache 配置中的各种超时设置,并减少了 sysctl.conf 中的各种网络设置,但似乎没有任何方法可以解决问题。
Apache 的错误日志中什么都没有。我尝试使用“ab”对 Apache 进行压力测试 - 它似乎会导致间歇性停顿稍快发生,但这就是我真正能从中判断的全部。Apache 和 MySQL 的最大连接数都设置为高值 - 实际并发连接数永远不会接近,除非在 Apache 连接数达到最大值时发生停顿。
我不太确定还能尝试什么。对于我可能遗漏的东西,您有什么想法或建议吗?
- 编辑 -
一些额外的观察。当发生停顿时,我注意到 ESTABLISHED 状态的连接数大幅增加,然后 CLOSE_WAIT 状态的连接数在几秒钟后也随之增加。
此外,当发生停顿时,“套接字侦听队列溢出次数”和“忽略侦听套接字的 SYN”数量会迅速增加。在停顿间隔期间,这些数字根本不会改变。
我不确定这些数字是失速的原因还是结果。如能提供进一步帮助,我将不胜感激。
答案1
我现在已经解决了这个问题,因此我发布解决方案以防其他人遇到同样的问题。
我忘了说我们所有的网络流量都是通过 HTTPS 传输的,这似乎是原因所在。在一次停滞期间,我使用 strace 和 pstack 查看其中一个空闲的 Apache 进程在做什么。它卡在等待 SSL 会话缓存的互斥锁。
查看 Apache 配置时,我注意到我们已启用 SSLSessionCache,超时时间为 5 分钟。禁用此功能即可解决问题。
我的猜测是会话缓存已满,然后 Apache 正在等待旧会话超时后再继续。
答案2
KeepAliveTimeout 指令
描述:服务器在持久连接上等待后续请求的时间 语法:KeepAliveTimeout 秒 默认值:KeepAliveTimeout 5 上下文:服务器配置,虚拟主机 状态:核心 模块:核心 Apache 在关闭连接之前等待后续请求的秒数。收到请求后,将应用 Timeout 指令指定的超时值。将 KeepAliveTimeout 设置为高值可能会导致负载过重的服务器出现性能问题。超时时间越长,等待与空闲客户端的连接而占用的服务器进程就越多。在基于名称的虚拟主机上下文中,将使用一组 NameVirtualHost 中第一个定义的虚拟主机(默认主机)的值。其他值将被忽略。
因此,在第一个(默认)主机上,我将设置 KeepAliveTimeout 3,删除配置中其他任何地方对该指令的进一步引用,然后重新运行压力测试以确保它是最大并发连接的问题。