为什么简单的瘦服务器在基准测试时停止响应16500个请求?

可能重复:
‘ab’程序在收到大量请求后会冻结,为什么?

这是一个简单的测试服务器:

require 'rubygems' require 'rack' require 'thin' class HelloWorld def call(env) [200, {"Content-Type" => "text/plain"}, "OK"] end end Rack::Handler::Thin.run HelloWorld.new, :Port => 9294 #I've tried with these added too, 'rack.multithread' => true, 'rack.multiprocess' => true 

这是一个测试运行:

 $ ab -n 20000 http://0.0.0.0:9294/sdf This is ApacheBench, Version 2.3  Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 0.0.0.0 (be patient) Completed 2000 requests Completed 4000 requests Completed 6000 requests Completed 8000 requests Completed 10000 requests Completed 12000 requests Completed 14000 requests Completed 16000 requests apr_poll: The timeout specified has expired (70007) Total of 16347 requests completed 

它在16500左右发生故障。为什么? 我怎样才能知道发生了什么。 是ruby中的GC还是OS X机器上有多个可用网络套接字的东西。 我有一个MPB 2.5 Ghz 6G内存。


编辑

经过一些讨论和测试各种事情后,似乎将net.inet.tcp.msl从15000改为1000ms会使测试高频Web服务器的问题随之消失。

 sudo sysctl -w net.inet.tcp.msl=1000 # this is only good for local development 

请参阅引用的问题以及此问题的答案。 ‘ab’程序在收到大量请求后会冻结,为什么?

为了清楚起见,我会在这里添加解决方案。 使用ab on os X进行高频测试的正确解决方案是将’net.inet.tcp.msl’设置从15000ms更改为1000ms。 这应该只在开发盒上完成。

  sudo sysctl -w net.inet.tcp.msl=1000 # this is only good for local development 

这个答案是在这里的评论中进行了很好的侦探工作之后找到的,来自对一个非常相似的问题的回答,这里是答案: https : //stackoverflow.com/a/6699135/155031

我想我已经明白了。

当ab连接到您的测试服务器时,它会打开一个源端口(例如,50134)并建立与目标端口(9294)的连接。

ab为源端口打开的端口由sysctl设置net.inet.ip.portrange.first和net.inet.ip.portrange.last确定。 例如,在我的机器上:

 philippotter ~ $ sysctl -a | grep ip.portrange net.inet.ip.portrange.lowfirst: 1023 net.inet.ip.portrange.lowlast: 600 net.inet.ip.portrange.first: 49152 net.inet.ip.portrange.last: 65535 net.inet.ip.portrange.hifirst: 49152 net.inet.ip.portrange.hilast: 65535 

这意味着ab的源端口将在49152到65535的范围内,总共16384。

HTTP是TCP协议。 当TCP连接关闭时,它将进入TIME_WAIT状态 ,同时等待剩余的传输中的数据包到达目的地。 这意味着在达到超时之前,端口不能用于任何其他目的。

因此,将所有这些放在一起,ab会非常快速地耗尽所有可用的源端口; 他们进入TIME_WAIT状态; 它们不能被重用; ab无法再创建连接。

你可以看到这个,如果你挂起时杀了ab,然后再次运行它 – 它将无法创建任何连接!