'ab'程序在收到大量请求后会冻结,为什么?

Hon*_*gli 37 sockets debugging networking throttling apachebench

每当我使用'ab'对Web服务器进行基准测试时,它会在发送大量请求后冻结一段时间,但仅在20秒左右后继续.

考虑以下用Ruby编写的HTTP服务器模拟器:

require 'socket'

RESPONSE = "HTTP/1.1 200 OK\r\n" +
           "Connection: close\r\n" +
           "\r\n" +
           "\r\n"

buffer = ""
server = TCPServer.new("127.0.0.1", 3000)  # Create TCP server at port 3000.
server.listen(1024)                        # Set backlog to 1024.
while true
    client = server.accept             # Accept new client.
    client.write(RESPONSE)             # Write a stock "HTTP" response.
    client.close_write                 # Shutdown write part of the socket.
    client.read(nil, buffer)           # Read all data from the socket.  
    client.close                       # Close it.
end
Run Code Online (Sandbox Code Playgroud)

然后我按如下方式运行ab:

ab -n 45000 -c 10 http://127.0.0.1:3000/
Run Code Online (Sandbox Code Playgroud)

在最初的几秒钟内,ab完成它的工作,并且使用100%CPU:

Benchmarking 127.0.0.1 (be patient)
Completed 4500 requests
Completed 9000 requests
Completed 13500 requests
Run Code Online (Sandbox Code Playgroud)

在大约13500个请求之后,系统CPU使用率降至0%.ab似乎被某种东西冻结了.问题不在服务器中,因为此时服务器正在调用accept().大约20秒后,ab继续,好像什么也没发生,并且将再次使用100%CPU,仅在几秒后再次冻结.

我怀疑内核中的某些内容会限制连接,但是为什么以及为什么?我正在使用OS X Leopard.我在Linux上也看到了类似的行为,虽然冻结发生在更多的请求中并且不会经常发生.

此问题阻止我运行大型HTTP基准测试.

mar*_*k4o 51

听起来你已经没有短暂的端口了.要检查,请使用该netstat命令并在该TIME_WAIT状态中查找数千个端口.

在Mac OS X上,默认的短暂端口范围是49152到65535,总共16384个端口.您可以使用以下sysctl命令检查:

$ sysctl net.inet.ip.portrange.first net.inet.ip.portrange.last
net.inet.ip.portrange.first: 49152
net.inet.ip.portrange.last: 65535

一旦用完了临时端口,通常需要等到TIME_WAIT状态到期(2*最大段生存期),直到您可以重用特定的端口号.您可以通过将范围更改为32768(这是Linux和Solaris上的默认值)来增加端口数.(最大端口号为65535,因此无法增加高端.)

$ sudo sysctl -w net.inet.ip.portrange.first=32768
net.inet.ip.portrange.first: 49152 -> 32768

请注意,IANA指定官方范围是49152到65535,某些防火墙可能会假设动态分配的端口属于该范围.您可能需要重新配置防火墙才能使用本地网络之外的更大范围.

也可以减少sysctl net.inet.tcp.msl控制TIME_WAIT状态持续时间的最大段寿命(在Mac OS X上),但这很危险,因为它可能导致较旧的连接与使用相同端口号的较新连接混淆.还有一些技巧涉及使用该SO_REUSEADDR选项绑定到特定端口,或者使用该SO_LINGER选项关闭,但这些也可能导致旧的和新的连接混淆,因此通常被认为是坏主意.

  • 对,就是那样.我按照http://www.brianp.net/2008/10/03/changing-the-length-of-the-time_wait-state-on-mac-os-x/上的说明更改了MSL,一切正常现在.谢谢! (2认同)

Fre*_*rik 25

而不是增加端口数量,改变TIME_WAITMac OS X上的长度.

这仅适用于开发,但我现在ab可以根据需要请求尽可能多的请求而无需超时.

将默认超时设置为1000毫秒,如下所示:

$ sudo sysctl -w net.inet.tcp.msl=1000
net.inet.tcp.msl: 15000 -> 1000
Run Code Online (Sandbox Code Playgroud)

另一个答案中提到的brianp.net页面已不再可用.您可以从Internet存档中检索它.