每当我使用“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
然后我按如下方式运行 ab:
ab -n 45000 -c 10 http://127.0.0.1:3000/
在最初的几秒钟内,ab 按预期完成其工作并使用 100% CPU:
Benchmarking 127.0.0.1 (be patient)
Completed 4500 requests
Completed 9000 requests
Completed 13500 requests
大约 13500 个请求后,系统 CPU 使用率降至 0%。 ab 似乎被什么东西冻结了。问题不在服务器上,因为此时服务器正在调用accept()。大约20秒后,ab就像什么都没发生一样继续运行,并且将再次使用100%的CPU,只是在几秒后再次冻结。
我怀疑内核中的某些东西正在限制连接,但是是什么以及为什么?我正在使用 OS X Leopard。我在 Linux 上也看到过类似的行为,尽管冻结发生在大量请求的情况下,而且发生的频率并不高。
这个问题使我无法运行大型 HTTP 基准测试。
听起来你已经用完了临时端口 http://www.ncftp.com/ncftpd/doc/misc/ephemeral_ports.html。要检查,请使用netstat http://developer.apple.com/documentation/Darwin/Reference/ManPages/man1/netstat.1.html命令并查找数千个端口TIME_WAIT http://www.softlab.ntua.gr/facilities/documentation/unix/unix-socket-faq/unix-socket-faq-2.html#ss2.7 state.
在 Mac OS X 上,默认临时端口范围是 49152 到 65535,总共 16384 个端口。您可以使用以下命令检查这一点sysctl http://developer.apple.com/documentation/Darwin/Reference/ManPages/man8/sysctl.8.html命令:
$ 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 指定的官方范围 http://www.iana.org/assignments/port-numbers是 49152 到 65535,某些防火墙可能会假定动态分配的端口属于该范围。您可能需要重新配置防火墙才能使用本地网络之外的更大范围。
还可以减少最大段寿命(sysctl net.inet.tcp.msl
在 Mac OS X 上),它控制TIME_WAIT
状态,但这很危险,因为它可能会导致旧连接与使用相同端口号的新连接混淆。还有一些技巧涉及使用以下命令绑定到特定端口SO_REUSEADDR
选项,或以SO_LINGER
选项,但这些也可能导致新旧连接混淆,因此通常被认为是坏主意。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)