记一次time_wait & close_wait的讨论总结

简介: TIME_WAIT是TCP连接关闭过程中的一个状态,具体是这么形成的:1 主动关闭端A:发FIN,进入FIN-WAIT-1状态,并等待......2 被动关闭端P:收到FIN后必须立即发ACK,进入CLOSE_WAIT状态,并等待.

image

TIME_WAIT是TCP连接关闭过程中的一个状态,具体是这么形成的:
1 主动关闭端A:发FIN,进入FIN-WAIT-1状态,并等待......
2 被动关闭端P:收到FIN后必须立即发ACK,进入CLOSE_WAIT状态,并等待......
3 主动关闭端A:收到ACK后进入FIN-WAIT-2状态,并等待......
4 被动关闭端P:发FIN,进入LAST_ACK状态,并等待......
5 主动关闭端A:收到FIN后必须立即发ACK,进入TIME_WAIT状态,等待2MSL后结束Socket
6 被动关闭端P:收到ACK后结束Socket

因此,TIME_WAIT状态是出现在主动发起连接关闭的一点,和是谁发起的连接无关,可以是client端,也可以是server端。
而从TIME_WAIT状态到CLOSED状态,有一个超时设置,这个超时设置是 2*MSL(RFC793定义了MSL为2分钟,Linux设置成了30s)

为什么需要TIME_WAIT?
主要有两个原因:
1)为了确保两端能完全关闭连接。
假设A服务器是主动关闭连接方,B服务器是被动方。如果没有TIME_WAIT状态,A服务器发出最后一个ACK就进入关闭状态,如果这个ACK对端没有收到,对端就不能完成关闭。对端没有收到ACK,会重发FIN,此时连接关闭,这个FIN也得不到ACK,而有TIME_WAIT,则会重发这个ACK,确保对端能正常关闭连接。
2)为了确保后续的连接不会收到“脏数据”
刚才提到主动端进入TIME_WAIT后,等待2MSL后CLOSE,这里的MSL是指(maximum segment lifetime,我们内核一般是30s,2MSL就是1分钟),网络上数据包最大的生命周期。这是为了使网络上由于重传出现的old duplicate segment都消失后,才能创建参数(四元组,源IP/PORT,目标IP/PORT)相同的连接,如果等待时间不够长,又创建好了一样的连接,再收到old duplicate segment,数据就错乱了。

TIME_WAIT 会导致什么问题
1) 新建连接失败
TIME_WAIT到CLOSED,需要2MSL=60s的时间。这个时间非常长。每个连接在业务结束之后,需要60s的时间才能完全释放。如果业务上采用的是短连接的方式,会导致非常多的TIME_WAIT状态的连接,会占用一些资源,主要是本地端口资源。
一台服务器的本地可用端口是有限的,也就几万个端口,由这个参数控制:
sysctl net.ipv4.ip_local_port_range
net.ipv4.ip_local_port_range = 32768 61000
当服务器存在非常多的TIME_WAIT连接,将本地端口都占用了,就不能主动发起新的连接去连其他服务器了。
这里需要注意,是主动发起连接,又是主动发起关闭的一方才会遇到这个问题。
如果是server端主动关闭client端建立的连接产生了大量的TIME_WAIT连接,这是不会出现这个问题的。除非是其中涉及到的某个客户端的TIME_WAIT连接都有好几万个了。

2)TIME_WAIT条目超出限制
这个限制,是由一个内核参数控制的:
sysctl net.ipv4.tcp_max_tw_buckets
net.ipv4.tcp_max_tw_buckets = 5000
超出了这个限制会报一条INFO级别的内核日志,然后继续关闭掉连接。并没有什么特别大的影响,只是增加了刚才提到的收到脏数据的风险而已。
另外的风险就是,关闭掉TIME_WAIT连接后,刚刚发出的ACK如果对端没有收到,重发FIN包出来时,不能正确回复ACK,只是回复一个RST包,导致对端程序报错,说connection reset。
因此net.ipv4.tcp_max_tw_buckets这个参数是建议不要改小的,改小会带来风险,没有什么收益,只是表面上通过netstat看到的TIME_WAIT少了些而已,有啥用呢?
并且,建议是当遇到条目不够,增加这个值,仅仅是浪费一点点内存而已。

如何解决time_wait?
1)最佳方案是应用改造长连接,但是一般不太适用
2)修改系统回收参数
设置以下参数
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_tw_recycle = 1
设置该参数会带来什么问题?
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_tw_recycle = 1
如果这两个参数同时开启,会校验源ip过来的包携带的timestamp是否递增,如果不是递增的话,则会导致三次握手建联不成功,具体表现为抓包的时候看到syn发出,server端不响应syn ack
通俗一些来讲就是,一个局域网有多个客户端访问您,如果有客户端的时间比别的客户端时间慢,就会建联不成功
治标不治本的方式:
放大端口范围
sysctl net.ipv4.ip_local_port_range
net.ipv4.ip_local_port_range = 32768 61000
放大time_wait的buckets
sysctl net.ipv4.tcp_max_tw_buckets
net.ipv4.tcp_max_tw_buckets = 180000

----------update 2020-02-22 关于tw_bucket之争------------
关于net.ipv4.tcp_max_tw_buckets到底要不要放大,目前云上ecs多数是设置了5000,我个人浅见觉得小了
image

简单来说 net.ipv4.tcp_max_tw_buckets的作用 是为了“优雅”的关闭连接
1,完整的关闭连接
2,避免有数据包重复
如果tw满了会怎样
TCP: time wait bucket table overflow
新内核
tw_bucket满了的话,会影响established状态的连接在finack的时候,直接进入closed状态
老内核
tw_bucket满了的话,会将tw_bucket里面的time_wait按照一定的规则(如LRU),将一批time_Wait直接进入closed状态 ,然后established状态发送finack后进入time_wait

tw的开销是什么?
1,特别少量的内存
2,占用本地端口
tw放大的好与坏?
1,放大的话需要更多的内存开销,但是几乎可以忽略不计
2,占用更多的本地端口,需要适当的放大本地端口范围,端口范围经过简单的测试,建议设置为tw的1.5倍
net.ipv4.ip_local_port_range
3,netstat 大量的扫描socket的时候(ss不会扫描,但是ss在slab内存特别高的时候,也有可能会引起抖动),极端情况下可能会引起性能抖动
4,tw放大,local_port_range放大,还可以配置复用以及快速回收等参数
5,使用快速回收可能会导致snat时间戳递增校验问题,不递增的话syn不响应

特殊场景的时候(本机会发起大量短链接的时候)
1, nginx结合php-fpm需要本地起端口,
2,nginx反代如(java ,容器等)
如下图所示,
tcp_tw_reuse参数需要结合net.ipv4.tcp_timestamps = 1 一起来用
即 服务器即做客户端,也做server端的时候
tcp_tw_reuse参数用来设置是否可以在新的连接中重用TIME_WAIT状态的套接字。注意,重用的是TIME_WAIT套接字占用的端口号,而不是TIME_WAIT套接字的内存等。这个参数对客户端有意义,在主动发起连接的时候会在调用的inet_hash_connect()中会检查是否可以重用TIME_WAIT状态的套接字。如果你在服务器段设置这个参数的话,则没有什么作用,因为服务器端ESTABLISHED状态的套接字和监听套接字的本地IP、端口号是相同的,没有重用的概念。但并不是说服务器端就没有TIME_WAIT状态套接字。
因此 该类场景最终建议是

net.ipv4.tcp_tw_recycle = 0 关掉快速回收
net.ipv4.tcp_tw_reuse = 1   开启tw状态的端口复用(客户端角色)
net.ipv4.tcp_timestamps = 1 复用需要timestamp校验为1 
net.ipv4.tcp_max_tw_buckets = 30000 放大bucket
net.ipv4.ip_local_port_range = 15000 65000 放大本地端口范围

内存开销测试

# ss -s
Total: 15254 (kernel 15288)
TCP:   15169 (estab 5, closed 15158, orphaned 0, synrecv 0, timewait 3/0), ports 0
Transport Total     IP        IPv6
*         15288     -         -        
RAW       0         0         0        
UDP       5         4         1        
TCP       11        11        0        
INET      16        15        1        
FRAG      0         0         0        
15000个socket消耗30多m内存
![image](https://yqfile.alicdn.com/b13fbcec765e806e839aba099a3369e0b7be7319.png)

----------万恶的分割线-----------
关于 close_wait
image

如上所示,CLOSE_WAIT的状态是 服务器端/客户端程序收到外部过来的FIN之后,响应了ACK包,之后就进入了 CLOSE_WAIT 状态。一般来说,如果一切正常,稍后服务器端/客户端程序 需要发出 FIN 包,进而迁移到 LAST_ACK 状态,收到对端过来的ACK后,完成TCP连接关闭的整个过程。
注:不管是服务器还是客户端,只要是被动接收第一个FIN的那一方才会进入CLOSE_WAIT状态

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
人工智能 网络协议 算法
5 分钟搞懂 ECN
5 分钟搞懂 ECN
4267 0
|
Kubernetes 负载均衡 监控
记一次k8s压测发生SLB 499的串流问题
对k8s集群中的pod进行压测,压测方式是直接访问k8s前的SLB, 压测表现是 SLB (CLB 7层监听)偶发返回499报错。 最终确认问题根因是五元组复用导致串流。 关键词: 偶发499 、压测、k8s
2591 4
记一次k8s压测发生SLB 499的串流问题
|
应用服务中间件 nginx 数据安全/隐私保护
Docker harbor私有仓库部署与管理-1
Docker harbor私有仓库部署与管理
375 0
|
7月前
|
消息中间件 Dubbo Java
深挖红黑树底层原理
深入解析红黑树底层原理,涵盖定义、特性、旋转与插删操作,结合Java源码实现及阿里生产实践,全面掌握高频面试与实战核心要点。
|
Web App开发 算法 网络协议
视频直播技术干货(十三):B站实时视频直播技术实践和音视频知识入门
本文讲述搭建这样一套最新流行的实时视频直播系统需要了解的背景知识以及系统的整体架构,希望对大家有帮助。
991 13
|
监控 前端开发 JavaScript
浏览器节能机制导致Websocket断连的坑
浏览器节能机制导致Websocket断连的坑
476 1
|
JavaScript Android开发 开发者
Mac搭建安卓模拟器(支持M1/M2/M3/M4)
Mac搭建安卓模拟器(支持M1/M2)
13732 50
|
缓存 安全 前端开发
Verdaccio私仓搭建的一些注意点和姿势
为什么会搞这个? 是想把我们公司的npm私有仓从nexus迁移出来. 我们目前和后端共用nexus,因为nexus也能管理maven这些! npm私有仓库独立出来,后续好推向整个公司!! 我们这里采用docker自己部署(用的是v4.6.x),方便后续滚动更新. 配置文件及模块缓存目录是从外部映射进去,维护比较弹性 外网访问是通过nginx代理,内网集群是通过安全组策略授权.
2052 0
|
存储 安全 关系型数据库
Mysql四种常见数据库引擎
四种mysql存储引擎 前言 数据库存储引擎是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建、查询、更新和删除数据。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能,使用不同的存储引擎,还可以 获得特定的功能。
12232 0
|
Linux 网络安全 开发工具

热门文章

最新文章