Cannot assign requested address問題解決
阿新 • • 發佈:2019-01-31
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的狀態轉換說起。
其中TIME_WAIT狀態的產生源自於TCP連線的結束,TCP要保證在所有可能的情況下使得所有的資料都能夠正確被投遞。當關閉一個 socket 連線時,主動關閉一端的 socket 將進入TIME_WAIT狀態,而被動關閉一方則轉入CLOSED狀態。
當一個socket關閉的時候,是通過兩端互發資訊的四次握手過程完成的,當一端呼叫close()時,就說明本端沒有資料再要傳送了。這好似看來在握手完成以後,socket就都應該處於關閉CLOSED狀態了。但這有兩個問題:
1. 我們沒有任何機制保證最後的一個ACK能夠正常送達
2. 網路上仍然有可能有殘餘的資料包(wandering duplicates,或老的重複資料包),我們也必須能夠正常處理。
正常的系統中,可分配的埠號是有限的,但是處於TIME_WAIT狀態的連線,雖然已經要確認關閉了,但是仍然佔住埠不撒手,一般需要2MSL的時間,現實時長大概在兩分鐘左右,所以在有限的埠使用完之後,新的請求沒有可以安放的地方,便出現了上述錯誤。
解決方案
修改sysctl.conf
vim /etc/sysctl.conf # 檔案中加入 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_tw_recycle = 1
減少短時間內的請求數
這一條需要結合具體場景分析,像本例的場景,是一個短時間內高併發,短連線,每次傳輸的時間較短,所以可以考慮加大每次的請求的資料傳輸量,總量一定的情況下,請求數下來,埠使用也能得到一定程度的緩解。通過直接傳送RTS來直接結束本次連線
這個方法暫時沒實踐,如果有時間,後期可能補上