1 TCP Time Wait 说明
在高并发 短连接 的TCP服务器上,当服务器处理完请求后立刻主动正常关闭连接。这个场景下会出现大量socket处于TIME_WAIT状态。
可以通过如果命令统计TCP连接的情况:
# netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
ESTABLISHED 257
TIME_WAIT 62
过多time wait主要会导致2个问题:
- 客户端主动发起的连接总数受 max open file数限制,过多连接导致达到max open file限制将无法创建新的连接。
- 客户端主动发起的连接总数也受可用端口号限制,端口号使用的上限是65535,如果过多TW连接将端口号耗尽同样无法再创建新的连接。
端口的范围由/etc/sysctl.conf文件中的如下参数控制:
net.ipv4.ip_local_port_range = 3500 65535
打开的文件句柄在/etc/security/limits.conf文件中配置:
# nofile - 可以打开的最大文件数, *通配符表示对所有用户有效
* soft nofile 65535
* hard nofile 65535
可以临时修改这2个配置来尝试解决,单根本还是要修改系统参数。
2 解决方法
修改操作系统内核文件/etc/sysctl.conf参数:
- tw_reuse,tw_recycle: 必须在客户端和服务端timestamps 开启时才管用(默认打开)。
- tw_reuse :只对客户端起作用,默认关闭,允许将TIME_WAIT状态的socket重新用于新的TCP连接,这样的好处就是如果出现大量TIME_WAIT状态的连接,也能够将这些连接占用的端口重新用于新的TCP连接。
- tw_recycle :对客户端和服务器同时起作用,默认关闭,表示快速回收TIME_WAIT状态的socket,不建议启用该参数,并且在4.x内核版本中已废弃。
2.1 对于客户端
- 作为客户端因为有端口65535问题,TIME_OUT过多直接影响处理能力,打开tw_reuse 即可解决,不建议同时打开tw_recycle,帮助不大。
- tw_reuse 帮助客户端1s完成连接回收,基本可实现单机6w/s请求。
- 如果内网压测场景,且客户端不需要接收连接,同时tw_recycle 会有一点点好处。
2.2 对于服务端
- 打开tw_reuse无效
- 线上环境 tw_recycle 不建议打开,因为一般的服务器、客户端都在NAT之后公网服务打开就可能造成部分连接失败。
- 如果服务器TIME_WAIT 过高,可以通过增加tcp_max_tw_buckets 参数值来解决。
2.3 操作示例
#客户端
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_tw_reuse=1 #系统默认0。当服务器当为客户端时有效(如反向代理访问后端),开启后客户端在1s内回收
net.ipv4.tcp_tw_recycle=0 #系统默认0。可关闭,但要调大tcp_max_tw_buckets,使用内存来支撑
#服务器端
net.ipv4.tcp_timestamps = 1 #系统默认1。会在tcp包头部记录时间戳。
net.ipv4.tcp_tw_recycle=0 #系统默认0。可关闭,但要调大tcp_max_tw_buckets,使用内存来支撑
net.ipv4.tcp_max_tw_buckets=655350
如果类型分的不是很清楚,那么3个参数全部启用即可:
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
然后sysctl -p 生效即可。
特别注意net.ipv4.tcp_tw_recycle 参数,如果设置为1, 可能会导致使用NAT 网络的连接失败,比如有k8s 或者 docker的环境.