Ruby 为什么一个简单的精简服务器在进行基准测试时会停止响应16500个请求?

Ruby 为什么一个简单的精简服务器在进行基准测试时会停止响应16500个请求?,ruby,thin,apachebench,Ruby,Thin,Apachebench,可能重复: 下面是一个简单的测试服务器: 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

可能重复:

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

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 <$Revision: 655654 $>
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
请参阅参考问题和此问题的答案

我想我明白了

当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连接关闭时,它进入,同时等待任何剩余的传输中数据包到达其目的地。这意味着在达到超时之前,端口不能用于任何其他目的

所以,把所有这些放在一起,ab会很快耗尽所有可用的源端口;他们进入时间等待状态;它们不能重复使用;ab无法再创建任何连接


如果在ab挂起时杀死它,然后再次运行它,您可以看到这一点——它将无法创建任何连接

为了澄清起见,我将在这里添加解决方案。在os X上使用ab进行高频测试的正确解决方案是将“net.inet.tcp.msl”设置从15000ms更改为1000ms。这只能在开发框上进行

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

这个答案是在这里的评论中进行了出色的侦查工作后发现的,来自对一个非常类似的问题的回答这里的答案是:

你找到原因了吗??一种可能的解释是,操作系统将套接字保持在“最近使用”状态,并且在几分钟内不会重用它。显然,人们可以重新配置操作系统的IP层来避免这种情况。如果有帮助的话,我可以在我的MBP上重现这种精确的行为。已完成16359项请求。不知道是什么原因造成的。嗯,大声想一想,这个数字可疑地接近16384…这个HN评论也注意到了问题:这个问题在另一个http服务器上,使用jmeter而不是ab:似乎OSX是这里的公共线程…听起来我们更接近这个问题了!但是为什么netstat-ptcp的输出没有充满等待的时间,为什么其他程序仍然可以打开连接?启动一个新的服务器并运行ab,最后一个请求似乎挂起在
tcp4 0 0 localhost.52892 localhost.http SYN_发送的
上,然后在一段时间后请求超时。(我试着在80端口而不是更高的端口上运行服务器)@sunkencity-hmm,问得好。也许现在还不是等待的时候。OSX上的ab客户端似乎经常出现故障。我已经尝试安装一个新的ab客户端,但即使我经常编译C代码,我也无法配置我的apache项目,我现在没有时间调试它。看起来很有趣,但可能不是问题:可能这是目标,但我没有编译它:只是添加到@RadioPiel所说的内容中——要尝试的命令是
$sudo sysctl-w net.inet.tcp.msl=1000
 sudo sysctl -w net.inet.tcp.msl=1000 # this is only good for local development