6

可能重复:
“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 <$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

它在 16500 附近崩盘。为什么?我怎样才能知道发生了什么。它是红宝石中的GC,还是OS X机器上具有可用网络套接字数量的东西。我有 MPB 2.5 Ghz 6G 内存。


编辑

经过这里的一些讨论并测试了各种东西,似乎将 net.inet.tcp.msl 从 15000 更改为 1000ms 使得使用 ab 测试高频 Web 服务器的问题消失了。

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

请参阅参考问题以及此问题的答案。'ab' 程序在大量请求后冻结,为什么?

4

2 回答 2

5

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

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

这个答案是在此处的评论中进行了出色的侦探工作之后发现的,并且来自对一个非常相似的问题的答案,这是答案:https ://stackoverflow.com/a/6699135/155031

于 2012-09-19T07:44:52.693 回答
2

我想我明白了。

当 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 挂起时将其杀死,然后再次运行它,您会看到这一点——它将无法创建任何连接!

于 2012-09-16T09:03:49.207 回答