1. 程式人生 > >Cannot assign requested address問題解決

Cannot assign requested address問題解決

TIME_WAIT過多及解決

問題場景

大量高併發日誌傳輸,短連線,每次在傳輸一定數量的日誌後,開始出現以下錯誤

    Failed to establish a new connection: [Errno 99] Cannot assign requested address

問題原因

通過下述命令可以檢視當前端口占用及分類

    netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'

    TIME_WAIT        27352
    SYN_SENT         4
    ESTABLISHED      58

  發現端口占用中處於TIME_WAIT狀態的有多達20000+,基本佔用了全部的埠,要詳細瞭解埠狀態,需要從TCP的狀態轉換說起。

image

  其中TIME_WAIT狀態的產生源自於TCP連線的結束,TCP要保證在所有可能的情況下使得所有的資料都能夠正確被投遞。當關閉一個 socket 連線時,主動關閉一端的 socket 將進入TIME_WAIT狀態,而被動關閉一方則轉入CLOSED狀態。

當一個socket關閉的時候,是通過兩端互發資訊的四次握手過程完成的,當一端呼叫close()時,就說明本端沒有資料再要傳送了。這好似看來在握手完成以後,socket就都應該處於關閉CLOSED狀態了。但這有兩個問題:
1. 我們沒有任何機制保證最後的一個ACK能夠正常送達
2. 網路上仍然有可能有殘餘的資料包(wandering duplicates,或老的重複資料包),我們也必須能夠正常處理。

  正常的系統中,可分配的埠號是有限的,但是處於TIME_WAIT狀態的連線,雖然已經要確認關閉了,但是仍然佔住埠不撒手,一般需要2MSL的時間,現實時長大概在兩分鐘左右,所以在有限的埠使用完之後,新的請求沒有可以安放的地方,便出現了上述錯誤。

解決方案

  1. 修改sysctl.conf

    vim /etc/sysctl.conf
    
    # 檔案中加入
    
    net.ipv4.tcp_tw_reuse = 1 
    net.ipv4.tcp_tw_recycle = 1 
  2. 減少短時間內的請求數
    這一條需要結合具體場景分析,像本例的場景,是一個短時間內高併發,短連線,每次傳輸的時間較短,所以可以考慮加大每次的請求的資料傳輸量,總量一定的情況下,請求數下來,埠使用也能得到一定程度的緩解。

  3. 通過直接傳送RTS來直接結束本次連線
    這個方法暫時沒實踐,如果有時間,後期可能補上

Refs