![Apache 使用 mod_reqtimeout 进行性能测试时出现的问题](https://linux22.com/image/654787/Apache%20%E4%BD%BF%E7%94%A8%20mod_reqtimeout%20%E8%BF%9B%E8%A1%8C%E6%80%A7%E8%83%BD%E6%B5%8B%E8%AF%95%E6%97%B6%E5%87%BA%E7%8E%B0%E7%9A%84%E9%97%AE%E9%A2%98.png)
我们在负载均衡器后面有 2 个 Apache 网络服务器,它们通过 mod ajp 连接到 2 个(JBoss)应用程序服务器。
移动设备通过 REST API 连接到这些网络服务器。
在我们的性能测试中,我们很快遇到了很多 NonHttpResponse: 错误,我们发现这些错误来自 mod_reqtimeout:
[Mon Mar 16 14:42:49.324705 2015] [reqtimeout:info] [pid 27914:tid 140628428449536] [client 1.2.3.4:48280] AH01382: Request header read timeout
...其配置如下:
<IfModule reqtimeout_module>
RequestReadTimeout header=10-20,minrate=500
RequestReadTimeout body=10,minrate=500
</IfModule>
我可以通过将那些值增加到
RequestReadTimeout header=20-60,minrate=100
但这不能解决问题,因为随着更多同时用户,问题再次出现(要求能够为 300 个并发用户提供服务 - 100 个工作正常,而 300 个用户时,我们遇到了超过 10,000 个请求标头读取超时错误)。我怀疑是 apaches KeepAlive、我们的 mod_ajp 配置和 mod_reqtimeout 之间的相互作用导致 mod_reqtimeout 得出存在 slowloris 攻击的结论(许多打开的连接什么也不做),我恳请您帮助调整这些参数。
另一个问题是 Web 服务器和应用程序服务器之间的防火墙,我怀疑它会杀死开放的空闲连接。我读到过完全停用 KeepAlive 来解决这个问题,但正如我所说,我们所有的客户端都是移动设备,所以这可能不是一个选择 (?)。
以下是其他配置(部分):
工人.属性:
worker.list=server
worker.maintain=60
worker.server.type=ajp13
worker.server.host=server
worker.server.port=15869
worker.server.socket_keepalive=True
worker.server.connection_pool_timeout=600
worker.server.ping_mode=A
worker.server.connection_ping_interval=60
mod_prefork:
<IfModule prefork.c>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
#MaxClients 256
MaxClients 300
MaxRequestsPerChild 0
</IfModule>
主服务器.conf:
Timeout 300
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 15
ssl.conf(移动设备通过 ssl 连接):
Timeout 1200
KeepAlive On
MaxKeepAliveRequests 0
KeepAliveTimeout 10
答案1
在看似本质上是反向代理的环境中,使用“prefork”MPM 是不寻常的,混合“worker”MPM 具有更好的可扩展性,但这不是问题所在。
通常,DoS 缓解措施最好(如果不是由您的 ISP 处理)在前端终止客户端请求的设备,根据您的描述,这是一个负载均衡器,而不是 Apache。任何有能力的负载均衡器都将支持 HTTP(即“第 7 层”),这可能会导致 HTTP 请求缓冲。如果负载均衡器正在终止 HTTPS,这也适用,但如果负载均衡器只是中继 HTTPS 连接(因为它无法看到 HTTP 请求以对其进行缓冲),则情况就不那么适用了。如果您的负载均衡器是一个简单的“第 3/4 层”NAT 类型负载均衡器,它也不适用。
至于超时的可能原因:
- 如果您的 SSL 实例
KeepAliveTimeout
与标头读取超时相同RequestReadTimeout
,则可能存在竞争,在传入客户端请求/标头的过程中达到保持活动超时。如果我尝试重现此问题,除了 AH01382 错误外,我还会收到 AH01991(SSL 输入过滤器读取失败)和 AH00567(请求失败:读取标头时出错)。但这可能无法解释所有问题。 - 客户端请求格式错误,过去很常见(例如 POST 后出现额外的 CR/LF,错误后重试时请求不完整)。不过我不知道目前有什么问题,这取决于您的客户群,更重要的是他们的连接性。
- 可能存在类似这样的错误最近的一个这导致“事件” MPM 出现虚假超时。
重现超时:
$ openssl s_client -connect myhost:443
GET / HTTP/1.1
Host: myhost.whatever.com
[server reply goes here]
GET / HTTP/1.1
Host:
您可以编写脚本以使其更容易,否则您必须在配置的 10 秒内输入/粘贴第一个请求和标头,然后输入但不完整在接下来的 10 秒内,您必须为第二个请求提交至少一行完整的内容(请求),然后等待。
减少 KeepAliveTimeout(默认值为 5 秒)可能会有所帮助。请注意,KeepAliveTimeout 是接收完整请求的时间。我认为下一步可能是mod_log_forensic
。
关于通过 AJP 连接到后端,您是否在阿帕奇Balancer
配置?如果我对您的系统理解正确,您给出的 Tomcat 配置不适用于从 Apache httpd 到 Tomcat 的连接。请参阅这里的选项。
/-> apache httpd + ajp -\ /-> tomcat/jboss
client -> load-balancer < > firewall <
\-> apache httpd + ajp -/ \-> tomcat/jboss