记一次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
目录
相关文章
|
网络安全 开发工具 C语言
升级OpenSSH
升级OpenSSH
979 0
|
Cloud Native Dubbo 应用服务中间件
阿里巴巴捐献的14个顶级开源项目,国内开源贡献第一!
代表性的项目包括龙蜥操作系统、Apache RocketMQ、Apache Dubbo、Spring Cloud Alibaba 等
|
Kubernetes 网络协议 调度
聊聊k8s中的hostport和NodePort
让服务基于节点暴露端口,大家最先想到的应该都是 nodeport 这种 service,他可以非常方便的为pod代理外部流量,那么 hostport 是什么呢?他和 nodeport 的区别是什么,今天我们来聊聊这个比较小众的 hostport。
7349 0
聊聊k8s中的hostport和NodePort
|
安全 Linux 网络安全
组网神器WireGuard安装与配置教程(超详细)
组网神器WireGuard安装与配置教程(超详细)
36611 2
|
消息中间件 存储 监控
消费者组consumer group详解-Kafka从入门到精通(九)
消费者组consumer group详解-Kafka从入门到精通(九)
消费者组consumer group详解-Kafka从入门到精通(九)
|
缓存 Linux 开发工具
CentOS 7- 配置阿里镜像源
阿里镜像官方地址http://mirrors.aliyun.com/ 1、点击官方提供的相应系统的帮助 :2、查看不同版本的系统操作: 下载源1、安装wget yum install -y wget2、下载CentOS 7的repo文件wget -O /etc/yum.
255275 0
|
9月前
|
存储 弹性计算 应用服务中间件
阿里云轻量应用服务器出新品通用型实例了,全球26个地域可选
近日,阿里云再度发力,推出了首款全新升级的轻量应用服务器——通用型实例。这款服务器实例不仅标配了200Mbps峰值公网带宽,更在计算、存储、网络等基础资源上进行了全面优化,旨在为中小企业和开发者提供更加轻量、易用、普惠的云计算服务,满足其对于通用计算小算力的迫切需求。目前,这款新品已在全球26个地域正式上线,为全球用户提供了更加便捷、高效的上云选择。
755 27
|
Kubernetes 负载均衡 网络协议
k8s网络诊断之我的流量去哪了
某客户反馈,生产业务的应用在做滚动更新时大量502报错,同时生产业务中pod设置了prestop来优雅下线(延迟关闭),但是在滚动更新时依然会有502的问题,由于生产环境流量比较高,决定搭建测试环境模拟复现该问题,实际复现过程中发现,pod切换完成后,客户端访问svc关联的SLB,应用会超时一段时间或者qps下降为0
2043 1
|
运维 Kubernetes 算法
资源画像,看得见的容器资源优化助手
日前,ACK 控制台在此基础上正式发布了资源画像功能,为用户提供了可视化的交互页面,便于管理员快速分析应用资源规格的合理性,并进行资源规格配置的变更。该功能目前已经正式开放公测,ACK 用户可以直接申请白名单试用。
资源画像,看得见的容器资源优化助手
|
存储 网络协议 算法
[网络] 5. TCP 链接的建立与释放~汇总
[网络] 5. TCP 链接的建立与释放~汇总
225 0