最近臨近產品發版,因為有性能壓力測試,開了20個並發請求同一個接口,然后遇到了這樣的問題 “java.net.connectException: Cannot assign requested address (connect failed)”。百度了一個看了N篇記錄,原因是客戶端頻繁的連服務器,由於每次連接都在很短的時間內結束,導致很多的TIME_WAIT,以至於用光了可用的端 口號,所以新的連接沒辦法綁定端口,因此就會跑出異常說 無法分配請求地址。這是一個客戶端的問題,與程序服務是沒有關系的,而我們目前的程序Http請求也是沒有線程池的。
關於服務器TCP請求的TIME_WAIT,linux下可用netstat -a|grep TIME_WAIT 這個命令去查看一下連接數。

同常有比較多條的一個列表,在程序跑的過程中,為了方便看到time_wait的數量是否增多,可以直接用命令netstat -ant|grep -i time_wait |wc -l 查看。

服務器在存在大量短連接的情況下,Linux的TCP棧一般都會生成大量的 TIME_WAIT 狀態的socket,有時候這個數量大到驚人的。而這個數量增大會占用系統的內核,而內核可不是無限的。
因此比較直接的解決方式就是修改系統內核相關的參數:
net.ipv4.ip_forward=1 表示開啟對於TCP時間戳的支持,若該項設置為為0,則net.ipv4.tcp_tw_reuse設置不起作用,該值系統默認是0
net.ipv4.tcp_syncookies = 1 表示開啟對於TCP時間戳的支持,若該項設置為為0,則net.ipv4.tcp_tw_reuse設置不起作用,該值系統默認是0
net.ipv4.tcp_tw_reuse = 1 表示開啟重用。允許將TIME-WAIT sockets重新用於新的TCP連接,默認為0,表示關閉
net.ipv4.tcp_tw_recycle = 1 表示開啟TCP連接中TIME-WAIT sockets的快速回收,默認為0,表示關閉
net.ipv4.tcp_fin_timeout = 30 修改系統默認的TIMEOUT時間,默認是60
修改方式:
編輯 /etc/sysctl.conf 文件,加入參數內容,以上5個參數是我查到的認為有效的結果,然后我的實際情況僅修改了其中三個:
net.ipv4.ip_forward=1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
編輯完成后執行命令 /sbin/sysctl -p 讓參數立即生效。至於氣他參數就看具體情況了。我這種修改方式是直接永久保存的,不會受網絡服務重啟,系統重啟等的影響,若要臨時修改請自行查詢命令。
然后我這邊再去跑測試程序,然后再用查看time_wait連接數的命令去查看,得到的結果是這個數量減少了,不會像之前累積的特別多,當然直到並發跑完都沒有在出現不法分配連接的異常,只是我這邊達到高峰的時候會降低響應效率,這個性能還是待優化的。
我這里的解決方式可能並不完美,但是緊急情況是可以采納采納的,關於壓力測試當然是我司測試伙伴配合的哈哈。
希望大家多多指教!
