ConnectException: Cannot assign requested address (connect failed)
原因
在存在大量短連接配接的情況下,雖然 socket 正常關閉,但預設60s後釋放,而不是立即釋放,是以處于TIME_WAIT狀态。Linux 連接配接端口(65535)用盡,就會造成這個異常。
檢視
檢視程序,有很多 TIME_WAIT 狀态的。
netstat -a | grep -i time_wait

總數
netstat -ant | grep -i time_wait | wc -l
解決
注意:需root權限
1. 臨時修改 sysctl
sysctl -w # 臨時修改指定系統參數的值
-p # 從指定的檔案加載系統參數,如不指定則加載/etc/sysctl.conf
-a # 顯示所有系統參數
# 端口釋放後的等待時間,預設為60s
sysctl -w net.ipv4.tcp_fin_timeout=30
# 或者更快回收設定
# 開啟對于TCP時間戳的支援,0關閉,則下面兩項設定不起作用
sysctl -w net.ipv4.tcp_timestamps=1
# 用戶端設定
# 允許端口重用,隻對用戶端起作用,開啟後用戶端在1s内回收time-wait socket
sysctl -w net.ipv4.tcp_tw_reuse=1
# 開啟TCP連接配接快速回收time-wait socket資源,預設為0關閉
# 用戶端不需要開啟
# 非高并發伺服器不建議開啟,開啟後在 3.5*RTO 内回收,RTO 200ms~ 120s,具體時間視網絡狀況
sysctl -w net.ipv4.tcp_tw_recycle=1
# 另外
# 檢視可用端口範圍,預設 32768~60999,不到3w
sysctl -a | grep port_range
# 可設定tcp_max_tw_buckets
# 當 time_wait 數量等于 tcp_max_tw_buckets,不産生新的 time_wait
sysctl -w net.ipv4.tcp_max_tw_buckets=5000
或者
echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
echo 1 > /proc/sys/net/ipv4/tcp_timestamps
echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse
echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle
sysctl -p
2. 永久修改
将配置寫入 /etc/sysctl.conf。
vim /etc/sysctl.conf
# 添加
net.ipv4.tcp_timestamps=1
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=1
sysctl -p