在大约256个同时请求的情况下,Apache的性能会大大降低

我运行的是一个相对较低stream量的站点,在站点更新之后,每周一次访问量大。 在这个峰值期间,现场performance与本周其余时间相比极其糟糕。 实际上,服务器上的负载仍然很低,可靠性在10%以下CPU和30%内存(硬件应该是完全矫枉过正我们实际正在做的),但由于某种原因,Apache似乎无法应付数量的请求。 我们在RHEL 5.7,kernel 2.6.18-274.7.1.el5,x86_64上运行apache 2.2.3。

试图在ab的下class时间重现这种行为,当超过大约256个用户时,我发现性能下降。 以最小的可能用例运行testing(可以检索静态文本文件,总共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中的线程限制引起的,所以我继续调整configuration,使可用线程数加倍,并防止线程池不断增长和收缩:

 <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) 

在冲刷文档(和堆栈交换)后,我不知道进一步的configuration设置,试图解决这个瓶颈。 有什么我失踪? 我应该开始寻找答案之外的Apache? 有没有其他人看到这种行为? 任何帮助将不胜感激。

编辑:

按照Ladadadada的build议,我对apache运行strace。 我用-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 

(… abdridged)

如果我正在阅读这个权利(和我一起承担,因为我不经常使用strace),系统调用都不能说明这些请求所花费的时间。 在请求甚至到达工作线程之前,它几乎看起来像瓶颈发生。

编辑2:

正如几个人所build议的那样,我再次在Web服务器上运行testing(以前testing是从中立的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) 

底线时间与基于互联网的testing类似,但在本地运行时似乎一直较差 。 更有趣的是,个人资料发生了巨大的变化。 而在大量的长时间运行的请求时间被用于“连接”之前,瓶颈似乎在处理或等待中。 我怀疑这实际上可能是一个单独的问题,以前被networking限制所掩盖。

再次从Apache主机的同一本地networking上的另一台机器运行testing,我看到更合理的结果:

 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) 

这两个testing一起提出了一些问题,但与此不同的是,现在有一个令人信服的情况是在某种负载下发生某种严重的networking瓶颈。 我认为接下来的步骤将是分别调查networking层。

在这种情况下我会做什么运行

 strace -f -p <PID> -tt -T -s 500 -o trace.txt 

在abtesting期间,在您的一个Apache进程中,直到您捕获其中一个缓慢的响应。 然后通过trace.txt

-tt-T选项为您提供每个系统调用的开始时间和持续时间的时间戳,以帮助识别较慢的时间戳。

您可能会发现一个缓慢的系统调用,例如open()stat()或者您可能会直接在其之后发现一个可能的多个poll()调用的快速调用。 如果您发现某个文件或networking连接正在运行(很有可能)通过跟踪向后查找,直到find该文件或连接句柄。 之前对同一个句柄的调用应该让你知道poll()正在等待什么。


好主意看着-c选项。 你确定在那个时候你所追踪的Apache孩子是否至less有一个缓慢的请求? (我甚至不知道你会如何做到这一点,除了在所有的孩子同时运行strace )。

不幸的是, strace并没有给我们一个正在运行的程序正在做什么的完整画面。 它只跟踪系统调用。 在一个程序内部可以发生很多事情,不需要向内核请求任何东西。 要确定是否发生这种情况,可以查看每个系统调用开始的时间戳。 如果你看到明显的差距,那就是时间到了。 这是不容易的,系统调用之间总是有小的差距。

既然你说的CPU使用率保持低,这可能不是过多的事情发生在系统调用之间,但值得检查。


仔细看看ab的输出:

响应时间的突然跳跃(看起来像150毫秒到3000毫秒之间没有任何响应时间)表明在某个地方有一个特定的超时发生在大约256个同时连接上面。 如果您的内存不足或CPU周期正常IO,则会出现更平滑的降级。

其次,缓慢的ab响应表明,3000ms是在connect阶段花费的。 几乎所有人都花了30毫秒左右,但5%花了3000毫秒。 这表明networking是问题。

你从哪里跑ab ? 你可以尝试从Apache机器在同一networking吗?

有关更多数据,请尝试在连接的两端运行tcpdump (最好使用两端运行的ntp ,以便可以同步两个捕获)并查找任何tcp重新传输。 Wireshark对分析转储特别有用,因为它突出显示了不同颜色的tcp重新传输,使其易于查找。

您可能还需要查看您有权访问的任何networking设备的日志。 最近我遇到了一个防火墙的问题,它可以以kb / s的速度处理带宽,但是它无法处理每秒接收的数据包数量。 它以每秒140,000个数据包为最高。 在你的ab运行一些快速math导致我相信你会看到每秒约13,000包(忽略5%的慢速请求)。 也许这是你已经达到的瓶颈。 事实上,这发生在256左右可能纯粹是一个巧合。