如何优化高并发TCP链接中产生的大量的TIME_WAIT的状态(nginx)

发布于:2024-06-14 ⋅ 阅读:(50) ⋅ 点赞:(0)

背景

线上有一套高并发的系统经常出现访问超时、服务不可用的告警,访问链路如下:client-> nginx-> web server,所以第一时间排查了nginx服务器,这台服务器主要是做前端web和后端的反向代理。排查nginx日志时发现大量的报错
,负载均衡时无法分配请求的地址。

(99: Cannot assign requested address) while connecting to upstream  

排查问题时,发现系统存在几万多个time_wait状态连接

netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'

由于time_wait连接会占用本地端口,而本地默认的最大端口数是65535,所以导致了端口不够用的情况

time_wait什么是

在 TCP 连接的生命周期中,TIME_WAIT 是连接终止过程中的一个状态

TIME_WAIT 状态有两个主要目的:
1、确保最后一个 ACK 包的可靠传输
2、允许旧的重复数据包消失

如何优化

1、系统内核参数调优

vi /etc/sysctl.conf
...
# 减少 TIME_WAIT 持续时间
net.ipv4.tcp_fin_timeout = 30 
# 启用端口复用
net.ipv4.tcp_tw_reuse = 1 
# 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭
net.ipv4.tcp_tw_recycle = 1
其他优化:

net.ipv4.ip_local_port_range = 1024 65535 增加可用端口范围,让系统拥有的更多的端口来建立链接,这里有个问题需要注意,对于这个设置系统就会从1025~65535这个范围内随机分配端口来用于连接,如果我们服务的使用端口比如8080刚好在这个范围之内,在升级服务期间,可能会出现8080端口被其他随机分配的链接给占用掉,这个原因也是文章开头提到的端口被占用的另一个原因
net.ipv4.ip_local_reserved_ports = 7005,8001-8100 针对上面的问题,我们可以设置这个参数来告诉系统给我们预留哪些端口,不可以用于自动分配。
...
#使内核参数生效
sysctl -p

2、nginx调整短链接为长链接

短连接是指SOCKET连接后发送后接收完数据后马上断开连接
长连接指建立SOCKET连接后不管是否使用都保持连接,但安全性较差

长连接比短连接从根本上减少了关闭连接的次数,减少了TIME_WAIT状态的产生数量,在高并发的系统中,这种方式的改动非常有效果,可以明显减少系统TIME_WAIT的数量