2009-08-01 93 views
32

每當我使用'ab'來對一個web服務器進行基準測試時,它會在發送很多請求後凍結一段時間,只有在20秒左右之後纔會繼續。'ab'程序在多次請求後會凍結,爲什麼?

考慮下面的HTTP服務器仿真器,用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 

我然後運行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基準測試。

回答

47

這聽起來像你用完ephemeral ports。要檢查,請使用netstat命令,並在TIME_WAIT狀態中查找數千個端口。

在Mac OS X上,默認臨時端口範圍是49152到65535,總共16384個端口。

 
$ 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 *最大段壽命),直到你可以重複使用一個特定的端口號:你可以用sysctl命令檢查此。通過將範圍從32768開始更改爲Linux和Solaris的默認值,您可以將端口數加倍。 (最大端口號是65535所以不能增加的高端。)

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

注意,official range designated by IANA是49152至65535,和一些防火牆可以假設動態分配的端口落入該範圍內。您可能需要重新配置防火牆,以便在本地網絡之外使用更大的範圍。

也可以降低最大片段生命週期(sysctl net.inet.tcp.msl在Mac OS X),其控制TIME_WAIT狀態的持續時間,但這是危險的,因爲它可能會導致舊的連接弄混了較新的是使用相同的端口號。還有一些涉及通過SO_REUSEADDR選項綁定到特定端口的技巧,或者通過SO_LINGER選項關閉,但這些技巧也可能導致舊的和新的連接混在一起,所以通常被認爲是不好的想法。

+1

是的,就是這樣。我按照http://www.brianp.net/2008/10/03/changing-the-length-of-the-time_wait-state-on-mac-os-x/上的說明更改了MSL,並且一切正常現在。謝謝! – Hongli 2009-08-02 11:58:38

16

除了增加端口數量,改變TIME_WAIT長度在Mac OS X

發展這隻適用,但現在我可以問ab儘可能多的請求,因爲我想不會超時。

設置默認的超時到1000毫秒,像這樣:

$ sudo sysctl -w net.inet.tcp.msl=1000 
net.inet.tcp.msl: 15000 -> 1000 

在對方的回答中提到的brianp.net頁面不再可用。您可以從internet archive檢索它。

相關問題