服务器连接TIME_WAIT分析
学好排除问题的方法,有助于提高生产力。
- 客户那边反馈,通过 OA 登录系统的时候提示连接数据库报错。登录服务器之后,出现大量
Cannot assign requested address
错误。
bash
# 报错信息如下所示
2019/12/06 06:26:31 [crit] 7#7: *164751 connect() to 192.168.100.80:80 failed (99: Cannot assign requested address)
while connecting to upstream, client: 125.xx.xx.xx, server: _, request: "GET /api/v1/user/xxx-login HTTP/1.1",
upstream: "http://192.168.100.80:80/api/v1/user/xxx-login", host: "xxx.xxx.com:xxx"
- 主要原因,由于客户端频繁连接服务器,而且每次连接很短就结束(有可能存在网络攻击的可能),导致出现很多
TIME_WAIT
的连接没有关闭,以至于把服务器上面可用的端口号都用完了,所以新的连接没办法绑定端口,即报错提示 Cannot assign requested address 问题。
bash
# 通过下述命令可以查看当前端口占用及分类
$ sudo netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'
CLOSE_WAIT 12
ESTABLISHED 356
FIN_WAIT2 12
TIME_WAIT 21332
SYN_SENT 4
- 在高并发的场景下,发送大量的短连接给服务器,就会出现端口不足。主动关闭连接的一方,连接会处在
TIME-WAIT
的状态下,需要等2MSL
时间后,系统才会回收这条连接,端口才可以继续被使用。
bash
# 开启对于TCP时间戳的支持
# 若该项设置为0的话,则下面一项设置不生效
$ sudo sysctl -w net.ipv4.tcp_timestamps = 1
# 开启TCP连接中TIME-WAIT对应的sockets快速回收
$ sudo sysctl -w net.ipv4.tcp_tw_recycle = 1
# 开启重用
# 允许将TIME-WAIT对应的sockets重新用于新的TCP连接
$ sudo sysctl -w net.ipv4.tcp_tw_reuse = 1
# 使配置的参数生效
# 对应的是/etc/sysctl.conf配置文件
$ sudo sysctl -p