谈谈TCP中的TIME_WAIT
所以,本文也来凑个热闹,来谈谈TIME_WAIT。
为什么要有TIME_WAIT?
TIME_WAIT是TCP主动关闭连接一方的一个状态,TCP断开连接的时序图如下:![]()
当主动断开连接的一方(Initiator)发送FIN包给对方,且对方回复了ACK+FIN,然后Initiator回复了ACK后就进入TIME_WAIT状态,一直将持续2MSL后进入CLOSED状态。
那么,我们来看如果Initiator不进入TIME_WAIT状态而是直接进入CLOSED状态会有什么问题?
考虑这种情况,服务器运行在80端口,客户端使用的连接端口是12306,数据传输完毕后服务端主动关闭连接,但是没有进入TIME_WAIT,而是直接计入CLOSED了。这时,客户端又通过同样的端口12306与服务端建立了一个新的连接。假如上一个连接过程中网络出现了异常,导致了某个包重传并延时到达了服务端,这时服务端就无法区分这个包是上一个连接的还是这个连接的。所以,主动关闭连接一方要等待2MSL,然后才能CLOSE,保证连接中的IP包都要么传输完成,要么被丢弃了。
TIME_WAIT会带来什么问题
系统中TIME_WAIT的连接数很多,会导致什么问题呢?这要分别针对客户端和服务器端来看的。
首先,如果是客户端发起了连接,传输完数据然后主动关闭了连接,这时这个连接在客户端就会处于TIMEWAIT状态,同时占用了一个本地端口。如果客户端使用短连接请求服务端的资源或者服务,客户端上将有大量的连接处于TIMEWAIT状态,占用大量的本地端口。最坏的情况就是,本地端口都被用光了,这时将无法再建立新的连接。
针对这种情况,对应的解决办法有2个:
1. 使用长连接,如果是http,可以使用keepalive
2. 增加本地端口可用的范围,比如Linux中调整内核参数:net.ipv4.ip_local_port_range
对于服务器自己,由于服务器是被动等待客户端建立连接的,因此即使服务器端有很多TIME_WAIT状态的连接,也不存在本地端口耗尽的问题。大量的TIME_WAIT的连接会导致如下问题:
1. 内存占用:因为每一个TCP连接都会有占用一些内存。
2. 在某些Linux版本上可能导致性能问题,因为数据包到达服务器的时候,内核需要知道数据包是属于哪个TCP连接的,在某些Linux版本上可能会遍历所有的TCP连接,所以大量TIME_WAIT的连接将导致性能问题。不过,现在的内核都对此进行了优化(待确认)。
那系统中处于TIME_WAIT状态的TCP连接数有上限吗?有的,这是通过net.ipv4.tcp_max_tw_buckets参数来控制的,默认值为180000。当超过了以后,系统就开始关闭这些连接,同时会在系统日志中打印日志。此时,可以将这个值调大一些,从这个参数的默认值就可以看出,对服务器自己,处于TIME_WAIT状态的TCP连接多点也没有什么关系,只是多占用些内存而已。
常见的TIMEWAIT错误参数
如果用TIME_WAIT作为关键字到网络上搜索,会得到很多关于如何减少TIME_WAIT数量的建议,其中有些建议是有错误或者有风险的,列举如下:
- net.ipv4.tcp_syncookies = 1,这个参数表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击。这个和TIME_WAIT没有什么关系。
- net.ipv4.tcp_tw_reuse = 1,这个参数表示重用TIME_WAIT的连接,重用的条件是TCP的4元组(源地址、源端口、目标地址、目标端口)要完全一致,而且开启了net.ipv4.tcp_timestamps,且新建立连接的使用的timestamp要大于当前连接的timestamp。所以,开启了这个参数对减少TIME_WAIT的TCP连接有点用,但条件太苛刻,所以实际用处不大。
- net.ipv4.tcp_tw_recycle = 1,这个参数表示开启TIME_WAIT回收功能,开启了这个参数后,将大大减小TIME_WAIT进入CLOSED状态的时间。但是开启了这个功能风险很大,可能会导致处于NAT后面的某些客户端无法建立连接。因为,开启这个功能后,它要求来自同一个IP的TCP新连接的timestamp要大于之前连接的timestamp。
- 查看当前配置 sysctl -a |grep net.ipv4.tcp_tw_reuse
TIMEWAIT的“正确”处理方法
简单总结一下我对于TIME_WAIT状态TCP连接的理解和处理方法:
1. TIME_WAIT状态的设计初衷是为了保护我们的。服务端不必担心系统中有几w个处于TIME_WAIT状态的TCP连接。可以调大net.ipv4.tcp_max_tw_buckets这个参数。
2. 使用短连接的客户端,需要关注TIME_WAIT状态的TCP连接,建议是采用长连接,同时调节参数net.ipv4.ip_local_port_range,增加本地可用端口的范围。
3. 可以开启net.ipv4.tcp_tw_reuse这个参数,但是实际用处有限。
4. 不要开启net.ipv4.tcp_tw_recycle这个参数,它带来的问题比用处大。
5. 某些Linux的发行版可以调节TIME_WAIT到CLOSED的等待时间(比如Ali的Linux内核提供了参数net.ipv4.tcp_tw_timeout ),可以稍微调小一点这个参数。
谈谈TCP中的TIME_WAIT的更多相关文章
- TCP中的TIME_WAIT状态
TIME_WAIT的存在有两大理由 1.可靠地实现TCP全双工连接的终止 2.允许老的可重复分节在网络中消失. 对于理由1,我们知道TCP结束需要四次挥手,若最后一次的客户端的挥手ACK丢失(假设是客 ...
- 谈谈 TCP 的 TIME_WAIT
由来 最近有同事在用 ab 进行服务压测,到 QPS 瓶颈后怀疑是起压机的问题,来跟我借测试机,于是我就趁机分析了一波起压机可能成为压测瓶颈的可能,除了网络 I/O.机器性能外,还考虑到了网络协议的问 ...
- TCP协议中的TIME_WAIT详细说明
文章目录 4.3设置TIME_WAIT状态的目的 4.3.1 实现TCP全双工连接的关闭 4.3.2 使过时的重复报文段失效 4.3.3 TIME_WAIT状态的自结束 4.3.4 TIME_WAIT ...
- tcp十种状态;关于tcp中time_wait状态(2MSL问题)
tcp十种状态 注意: 当一端收到一个FIN,内核让read返回0来通知应用层另一端已经终止了向本端的数据传送 发送FIN通常是应用层对socket进行关闭的结果 关于tcp中time_wait状态的 ...
- TCP连接(Time_Wait、Close_Wait)说明
修改Time_Wait和CLOSE_WAIT时间 修改Time_Wait参数的方法 (在服务端修改)Windows下在HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlS ...
- TCP连接和 time_wait、close_waite
TCP连接和 time_wait.close_waite tags:time_wait close_waite RST TCP 引言:前两天朋友公司的服务器垮掉了,最后查出的原因是发现大量的time_ ...
- TCP连接的TIME_WAIT和CLOSE_WAIT 状态解说【转】
相信很多运维工程师遇到过这样一个情形: 用户反馈网站访问巨慢, 网络延迟等问题, 然后就迫切地登录服务器,终端输入命令"netstat -anp | grep TIME_WAIT | wc ...
- TCP连接的TIME_WAIT和CLOSE_WAIT 状态解说
相信很多运维工程师遇到过这样一个情形: 用户反馈网站访问巨慢, 网络延迟等问题, 然后就迫切地登录服务器,终端输入命令"netstat -anp | grep TIME_WAIT | wc ...
- TCP 中的三次握手和四次挥手
Table of Contents 前言 数据报头部 三次握手 SYN 攻击 四次挥手 半连接 TIME_WAIT 结语 参考链接 前言 TCP 中的三次握手和四次挥手应该是非常著名的两个问题了,一方 ...
随机推荐
- bzoj4195 [Noi2015]程序自动分析——并查集
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4195 突然在这道大水题上WA了半天... 思路很简单,离线处理询问,先把 = 的都加到并查集 ...
- 转贴:CSS伪类与CSS伪元素的区别及由来具体说明
关于两者的区别,其实是很古老的问题.但是时至今日,由于各种网络误传以及一些不负责任的书籍误笔,仍然有相当多的人将伪类与伪元素混为一谈,甚至不乏很多CSS老手.早些年刚入行的时候,我自己也被深深误导,因 ...
- Java多线程系列二——Thread类的方法
Thread实现Runnable接口并实现了大量实用的方法 public static native void yield(); 此方法释放CPU,但并不释放已获得的锁,其它就绪的线程将可能得到执行机 ...
- Kettle 连接 oracle 报错:could not be found, make sure the 'Oracle' driver (jar file) is installed.
我的ETL版本为6.0 oracle版本为11.2.0 报错如下: Driver class 'oracle.jdbc.driver.OracleDriver' could not be found, ...
- C# 简单实现直线方程,抛物线方程(转载)
http://www.cnblogs.com/hsiang/archive/2017/01/17/6294864.html 本例子是简单的在WinForm程序中实现在坐标系中绘制直线方程,抛物线方程, ...
- 编写第一Spring程序
构建Spring项目 通过https://start.spring.io/来构建项目,在这里我选择了两个依赖,web 和 Actuator. 项目结构 通过eclipse导入项目,可以看到这是一个标准 ...
- laravel 模型 $table $guarded $hidden
首先以App\User模型为例 1.$table属性 表名,对应数据库中的表名 2.guarded)属性 guarded表示在create()方法中不能被赋值的字段 3.$hidden属性 $hid ...
- Spring.Net学习笔记(5)-集合注入
一.开发环境 系统:Win10 编译器:VS2013 .net版本:.net framework4.5 二.涉及程序集 Spring.Core.dll 1.3.1 Common.Loggin.dll ...
- self和super的区别
(1)self调用自己方法,super调用父类方法 (2)self是类,super是预编译指令 (3)[self class]和[super class]输出是一样的 ①当使用 self 调用方法时, ...
- python学习笔记(5)—— tuple 本质探究
>>> t=(1,2,3,['a','b','c'],4,5) >>> t[3][0]='x' >>> t (1, 2, 3, ['x', 'b' ...