“ab”程序在许多请求后冻结,为什么? [英] 'ab' program freezes after lots of requests, why?

查看:274
本文介绍了“ab”程序在许多请求后冻结,为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

  require'socket'

RESPONSE =HTTP / 1.1 200 OK\\\\
+
连接:close\r\\\
+
\r\\\
+
\\

buffer =
server = TCPServer.new(127.0.0.1,3000)#在端口3000创建TCP服务器
服务器。 listen(1024)#将积压设置为1024.
while true
client = server.accept#接受新客户端。
client.write(RESPONSE)#写一个库存HTTP响应。
client.close_write#关闭写套接字的一部分。
client.read(nil,buffer)#从套接字读取所有数据。
client.close#关闭它。
end

然后我运行ab,如下所示:

  ab -n 45000 -c 10 http://127.0.0.1:3000/ 

在前几秒钟内,ab按照应用程序执行其工作,并使用100%的CPU:

 code>基准127.0.0.1(耐心)
已完成4500个请求
已完成9000个请求
完成13500个请求

在约13500个请求之后,系统CPU使用率下降到0%。 ab似乎被冻结在某物上。问题不在于服务器,因为在这一刻,服务器正在调用accept()。大约20秒后,ab继续,好像没有发生任何事情,并将再次使用100%的CPU,只能在几秒钟后再次冻结。



我怀疑内核中的某些东西在调节连接,但是为什么?我使用的是OS X Leopard。我也曾在Linux上看到类似的行为,尽管冻结发生在更多的请求中,并不经常发生。



这个问题阻止我运行大型HTTP基准测试。

解决方案

这听起来像是用完了短暂端口。要检查,请使用 netstat 命令,并在 TIME_WAIT 状态。 p>

在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 在Mac OS X),它控制 TIME_WAIT 状态的持续时间,但这是这可能会导致较旧的连接与使用相同端口号的较新连接混淆。还有一些技巧涉及使用 SO_REUSEADDR 选项绑定到特定端口,或者使用 SO_LINGER 选项关闭,但是那些也可能导致旧的和新的连接被混合,所以通常被认为是坏的想法。


Whenever I use 'ab' to benchmark a web server, it will freeze for a while after having sent lots of requests, only to continue after 20 seconds or so.

Consider the following HTTP server simulator, written in Ruby:

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

I then run ab as follows:

ab -n 45000 -c 10 http://127.0.0.1:3000/

During the first few seconds, ab does its job as it's supposed to and uses 100% CPU:

Benchmarking 127.0.0.1 (be patient)
Completed 4500 requests
Completed 9000 requests
Completed 13500 requests

After about 13500 requests, system CPU usage drops to 0%. ab seems to be frozen on something. The problem is not in the server because at this moment, the server is calling accept(). After about 20 seconds ab continues as if nothing happened, and will use 100% CPU again, only to freeze again after several seconds.

I suspect something in the kernel is throttling connections, but what and why? I'm using OS X Leopard. I've seen similar behavior on Linux as well, though the freeze happens at a much larger number of requests and doesn't happen so often.

This problem prevents me from running large HTTP benchmarks.

解决方案

It sounds like you are running out of ephemeral ports. To check, use the netstat command and look for several thousand ports in the TIME_WAIT state.

On Mac OS X the default ephemeral port range is 49152 to 65535, for a total of 16384 ports. You can check this with the sysctl command:

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

Once you run out of ephemeral ports, you will normally need to wait until the TIME_WAIT state expires (2 * maximum segment lifetime) until you can reuse a particular port number. You can double the number of ports by changing the range to start at 32768, which is the default on Linux and Solaris. (The maximum port number is 65535 so you cannot increase the high end.)

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

Note that the official range designated by IANA is 49152 to 65535, and some firewalls may assume that dynamically assigned ports fall within that range. You may need to reconfigure your firewall in order to make use of a larger range outside of your local network.

It is also possible to reduce the maximum segment lifetime (sysctl net.inet.tcp.msl on Mac OS X), which controls the duration of the TIME_WAIT state, but this is dangerous as it could cause older connections to get mixed up with newer ones that are using the same port number. There are also some tricks involving binding to specific ports with the SO_REUSEADDR option, or closing with the SO_LINGER option, but those also could cause old and new connections to be mixed up, so are generally considered to be bad ideas.

这篇关于“ab”程序在许多请求后冻结,为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆