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
其他:
非高并发的情况下,注意检查是否代码bug,是否循环不断创建连接造成。