我正在运行一个流量相对较低的网站,在网站更新后,每周一次的访问者数量会激增。在此高峰期间,与一周的其余时间相比,站点性能非常差。服务器上的实际负载仍然非常低,可靠地在10%的CPU和30%的RAM下(对于我们正在做的事情,硬件应该是完全过大了),但是由于某种原因,Apache似乎无法应付数量的请求。我们正在RHEL 5.7,内核2.6.18-274.7.1.el5,x86_64上运行apache 2.2.3。
尝试用ab在下班时间重现这种行为,我发现当超过大约256个用户时,性能会大大下降。以我能想到的最小用例运行测试(检索到静态文本文件,总共223个字节),在同时进行245个同时请求的情况下,性能始终是正常的:
Connection Times (ms)
min mean[+/-sd] median max
Connect: 15 25 5.8 24 37
Processing: 15 65 22.9 76 96
Waiting: 15 64 23.0 76 96
Total: 30 90 27.4 100 125
Percentage of the requests served within a certain time (ms)
50% 100
66% 108
75% 111
80% 113
90% 118
95% 120
98% 122
99% 123
100% 125 (longest request)
但是,一旦我处理了265个并发请求,其中的一部分就会开始花费大量时间来完成:
Connection Times (ms)
min mean[+/-sd] median max
Connect: 13 195 692.6 26 3028
Processing: 15 65 21.3 72 100
Waiting: 15 65 21.3 71 99
Total: 32 260 681.7 101 3058
Percentage of the requests served within a certain time (ms)
50% 101
66% 108
75% 112
80% 116
90% 121
95% 3028
98% 3040
99% 3044
100% 3058 (longest request)
这些结果在多次运行中非常一致。由于还有其他流量进入该盒子,因此我不确定确切的硬截止点在哪里,如果有的话,但似乎可疑接近256。
自然地,我认为这是由prefork中的线程限制引起的,因此我继续进行了配置调整,以使可用线程的数量增加一倍,并防止线程池不必要地增长和收缩:
<IfModule prefork.c>
StartServers 512
MinSpareServers 512
MaxSpareServers 512
ServerLimit 512
MaxClients 512
MaxRequestsPerChild 5000
</IfModule>
mod_status确认我现在正在使用512个可用线程运行
8 requests currently being processed, 504 idle workers
但是,尝试265个并发请求仍然会产生与之前几乎相同的结果
Connection Times (ms)
min mean[+/-sd] median max
Connect: 25 211 714.7 31 3034
Processing: 17 94 28.6 103 138
Waiting: 17 93 28.5 103 138
Total: 57 306 700.8 138 3071
Percentage of the requests served within a certain time (ms)
50% 138
66% 145
75% 150
80% 161
90% 167
95% 3066
98% 3068
99% 3068
100% 3071 (longest request)
在仔细阅读文档(和Stack Exchange)之后,我不知所措,无法尝试进一步的配置设置来解决此瓶颈。有什么我想念的吗?我应该开始在Apache之外寻找答案吗?有人看到过这种行为吗?任何帮助将不胜感激。
编辑:
根据Ladadadada的建议,我反对Apache。我尝试使用-tt和-T几次,却找不到任何异常。然后,我尝试对所有当前正在运行的apache进程运行strace -c,并得到以下信息:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
22.09 0.317836 5 62128 4833 open
19.91 0.286388 4 65374 1896 lstat
13.06 0.187854 0 407433 pread
10.70 0.153862 6 27076 semop
7.88 0.113343 3 38598 poll
6.86 0.098694 1 100954 14380 read
(...简略)
如果我没看错(并忍受,因为我不经常使用strace),那么没有系统调用可以解释这些请求所花费的时间。在请求甚至到达工作线程之前,似乎几乎已经出现了瓶颈。
编辑2:
正如几个人建议的那样,我再次在Web服务器本身上运行了该测试(以前该测试是从中立的Internet位置运行的)。结果令人惊讶:
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 11 6.6 12 21
Processing: 5 247 971.0 10 4204
Waiting: 3 245 971.3 7 4204
Total: 16 259 973.3 21 4225
Percentage of the requests served within a certain time (ms)
50% 21
66% 23
75% 24
80% 24
90% 26
95% 4225
98% 4225
99% 4225
100% 4225 (longest request)
底线时间类似于基于Internet的测试,但是在本地运行时似乎总是更糟。更有趣的是,配置文件已发生了巨大变化。之前,在长时间运行的请求中,大部分时间都花在了“连接”上,而现在瓶颈正在处理或等待中。我怀疑这可能实际上是一个单独的问题,以前曾被网络限制所掩盖。
从与Apache主机位于同一局域网中的另一台计算机再次运行测试,我看到了更为合理的结果:
Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 2 0.8 2 4
Processing: 13 118 99.8 205 222
Waiting: 13 118 99.7 204 222
Total: 15 121 99.7 207 225
Percentage of the requests served within a certain time (ms)
50% 207
66% 219
75% 220
80% 221
90% 222
95% 224
98% 224
99% 225
100% 225 (longest request)
这两个测试一起提出了许多问题,但与此分开的是,对于在一定量的负载下发生的某种严重的网络瓶颈,现在有一个令人信服的理由。我认为下一步将分别研究网络层。