再谈应用环境下的 TIME_WAIT 和 CLOSE_WAIT
转自:http://blog.csdn.net/shootyou/article/details/6622226
昨天解决了一个 HttpClient 调用错误导致的服务器异常,具体过程如下:
http://blog.csdn.net/shootyou/article/details/6615051
里头的分析过程有提到,通过查看服务器网络状态检测到服务器有大量的 CLOSE_WAIT 的状态。
在服务器的日常维护过程中,会经常用到下面的命令:
- netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
它会显示例如下面的信息:
TIME_WAIT 814
CLOSE_WAIT 1
FIN_WAIT1 1
ESTABLISHED 634
SYN_RECV 2
LAST_ACK 1
常用的三个状态是:ESTABLISHED 表示正在通信,TIME_WAIT 表示主动关闭,CLOSE_WAIT 表示被动关闭。
具体每种状态什么意思,其实无需多说,看看下面这种图就明白了,注意这里提到的服务器应该是业务请求接受处理的一方:
这么多状态不用都记住,只要了解到我上面提到的最常见的三种状态的意义就可以了。一般不到万不得已的情况也不会去查看网络状态,如果服务器出了异常,百分之八九十都是下面两种情况:
1.服务器保持了大量 TIME_WAIT 状态
2.服务器保持了大量 CLOSE_WAIT 状态
因为 Linux 分配给一个用户的文件句柄是有限的(可以参考:http://blog.csdn.net/shootyou/article/details/6579139),而 TIME_WAIT 和 CLOSE_WAIT 两种状态如果一直被保持,那么意味着对应数目的通道就一直被占着,而且是“占着茅坑不使劲”,一旦达到句柄数上限,新的请求就无法被处理了,接着就是大量 Too Many Open Files 异常,tomcat 崩溃。。。
下面来讨论下这两种情况的处理方法,网上有很多资料把这两种情况的处理方法混为一谈,以为优化系统内核参数就可以解决问题,其实是不恰当的,优化系统内核参数解决 TIME_WAIT 可能很容易,但是应对 CLOSE_WAIT 的情况还是需要从程序本身出发。现在来分别说说这两种情况的处理方法:
1.服务器保持了大量 TIME_WAIT 状态
这种情况比较常见,一些爬虫服务器或者 WEB 服务器(如果网管在安装的时候没有做内核参数优化的话)上经常会遇到这个问题,这个问题是怎么产生的呢?
从上面的示意图可以看得出来,TIME_WAIT 是主动关闭连接的一方保持的状态,对于爬虫服务器来说他本身就是“客户端”,在完成一个爬取任务之后,他就会发起主动关闭连接,从而进入 TIME_WAIT 的状态,然后在保持这个状态 2MSL(max segment lifetime)时间之后,彻底关闭回收资源。为什么要这么做?明明就已经主动关闭连接了为啥还要保持资源一段时间呢?这个是 TCP/IP 的设计者规定的,主要出于以下两个方面的考虑:
1.防止上一次连接中的包,迷路后重新出现,影响新连接(经过 2MSL,上一次连接中所有的重复包都会消失)
2.可靠的关闭 TCP 连接。在主动关闭方发送的最后一个 ack(fin) ,有可能丢失,这时被动方会重新发 fin, 如果这时主动方处于 CLOSED 状态 ,就会响应 rst 而不是 ack。所以主动方要处于 TIME_WAIT 状态,而不能是 CLOSED 。另外这么设计 TIME_WAIT 会定时的回收资源,并不会占用很大资源的,除非短时间内接受大量请求或者受到攻击。
关于 MSL 引用下面一段话:
- MSL 為一個 TCP Segment (某一塊 TCP 網路封包) 從來源送到目的之間可續存的時間 (也就是一個網路封包在網路上傳輸時能存活的時間),由於 RFC 793 TCP 傳輸協定是在 1981 年定義的,當時的網路速度不像現在的網際網路那樣發達,你可以想像你從瀏覽器輸入網址等到第一個 byte 出現要等 4 分鐘嗎?在現在的網路環境下幾乎不可能有這種事情發生,因此我們大可將 TIME_WAIT 狀態的續存時間大幅調低,好讓 連線埠 (Ports) 能更快空出來給其他連線使用。
再引用网络资源的一段话:
- 值得一说的是,对于基于 TCP 的 HTTP 协议,关闭 TCP 连接的是 Server 端,这样,Server 端会进入 TIME_WAIT 状态,可 想而知,对于访问量大的 Web Server,会存在大量的 TIME_WAIT 状态,假如 server 一秒钟接收 1000 个请求,那么就会积压 240 * 1000 = 240,000 个 TIME_WAIT 的记录,维护这些状态给 Server 带来负担。当然现代操作系统都会用快速的查找算法来管理这些 TIME_WAIT,所以对于新的 TCP 连接请求,判断是否 hit 一个 TIME_WAIT 不会太费时间,但是有这么多状态要维护总是不好。
- HTTP 协议 1.1 版规定 default 行为是 Keep-Alive,也就是会重用 TCP 连接传输多个 request/response,一个主要原因就是发现了这个问题。
也就是说 HTTP 的交互跟上面画的那个图是不一样的,关闭连接的不是客户端,而是服务器,所以 web 服务器也是会出现大量的 TIME_WAIT 的情况的。
- #对于一个新建连接,内核要发送多少个 SYN 连接请求才决定放弃,不应该大于 255,默认值是 5,对应于 180 秒左右时间
- net.ipv4.tcp_syn_retries=2
- #net.ipv4.tcp_synack_retries=2
- #表示当 keepalive 起用的时候,TCP 发送 keepalive 消息的频度。缺省是 2 小时,改为 300 秒
- net.ipv4.tcp_keepalive_time=1200
- net.ipv4.tcp_orphan_retries=3
- #表示如果套接字由本端要求关闭,这个参数决定了它保持在 FIN-WAIT-2 状态的时间
- net.ipv4.tcp_fin_timeout=30
- #表示 SYN 队列的长度,默认为 1024,加大队列长度为 8192,可以容纳更多等待连接的网络连接数。
- net.ipv4.tcp_max_syn_backlog = 4096
- #表示开启 SYN Cookies。当出现 SYN 等待队列溢出时,启用 cookies 来处理,可防范少量 SYN 攻击,默认为0,表示关闭
- net.ipv4.tcp_syncookies = 1
- #表示开启重用。允许将 TIME-WAIT sockets 重新用于新的 TCP 连接,默认为0,表示关闭
- net.ipv4.tcp_tw_reuse = 1
- #表示开启 TCP 连接中 TIME-WAIT sockets 的快速回收,默认为 0,表示关闭
- net.ipv4.tcp_tw_recycle = 1
- ##减少超时前的探测次数
- net.ipv4.tcp_keepalive_probes=5
- ##优化网络设备接收队列
- net.core.netdev_max_backlog=3000
net.ipv4.tcp_fin_timeout
net.ipv4.tcp_keepalive_*
再谈应用环境下的 TIME_WAIT 和 CLOSE_WAIT的更多相关文章
- 再谈应用环境下的TIME_WAIT和CLOSE_WAIT
昨天解决了一个HttpClient调用错误导致的服务器异常,具体过程如下: http://blog.csdn.net/shootyou/article/details/6615051 里头的分析过程有 ...
- 谈应用环境下的TIME_WAIT和CLOSE_WAIT[转]
昨天解决了一个HttpClient调用错误导致的服务器异常,具体过程如下: http://blog.csdn.net/shootyou/article/details/6615051 里头的分析过程有 ...
- windows 下解决 Time_Wait 和 CLOSE_WAIT 方法
修改Time_Wait参数的方法 (在服务端修改)Windows下在HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Tcpip/Paramet ...
- 再谈fedora23下Virutalbox的安装. --问题的关键在于 安装kernel-devel包
首先, 要使用 virutalbox的 rpm 安装包 进行安装. 在安装的过程中, 如果提示 有一些包, 没有, dependencies not resolved, 比如libQt..libvpx ...
- 再谈fedora下的音乐和视频播放器的安装
rpm包就相当于windows下的exe,已经是编译后的二进制代码,可以使用rpm命令或dnf install ???.rpm来安装 lnux下软件的安装跟windows不同, 后者要到处去找, 要做 ...
- 再谈Retina下1px的解决方案
https://www.w3cplus.com/css/fix-1px-for-retina.html
- C++ Primer 学习笔记_32_STL实践与分析(6) --再谈string类型(下)
STL实践与分析 --再谈string类型(下) 四.string类型的查找操作 string类型提供了6种查找函数,每种函数以不同形式的find命名.这些操作所有返回string::size_typ ...
- C++ Primer 学习笔记_44_STL实践与分析(18)--再谈迭代器【下】
STL实践与分析 --再谈迭代器[下] 三.反向迭代器[续:习题] //P355 习题11.19 int main() { vector<int> iVec; for (vector< ...
- TCP连接(Time_Wait、Close_Wait)说明
修改Time_Wait和CLOSE_WAIT时间 修改Time_Wait参数的方法 (在服务端修改)Windows下在HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlS ...
随机推荐
- MVC.Net:对MVC5部署时出现403.14错误的解决方法
当我们部署MVC5到IIS 7的时候,有时会出现403.14的错误,如下图: 对于这个错误的解决方法就是在应用程序的web.config的system.webServer节点中加入这一句: <m ...
- Java学习笔记之 IO包 字节流
IO包最重要的五个类和一个接口 File/OutputStream/InputStream(字节流)/Writer/Reader(字符流) 一个接口:Serializable File类: 字节流 ...
- [Jest] Use property matchers in snapshot tests with Jest
With the right process in place, snapshot tests can be a great way to detect unintended changes in a ...
- C++对象模型——关于对象(第一章)
第一章 关于对象 在C语言中,"数据"和"处理数据的操作(函数)"是分开声明的,也就是说,语言本身并没有支持"数据和函数"之间的关联性 ...
- mysql中DATETIME类型与TIMESTAMP的区别
1.DATETIME的日期范围是1001--9999年,TIMESTAMP的时间范围是1970--2038年. 2.DATETIME存储时间与时区无关,TIMESTAMP存储时间与时区有关,显示的值也 ...
- Appium - xpath
基本属性定位 以淘宝app为例,定位左上角扫一扫按钮 1.可以通过text文本定位到 //*[@text='text文本属性'] # 定位text driver.find_element_by_xpa ...
- Oracle 字符拼接
使用的是ORACLE中的cast函数: 官方链接: https://docs.oracle.com/cd/E11882_01/server.112/e41084/functions023.htm#SQ ...
- Linux 安装配置JDK 、 MySQL 、nginx
今天我来讲一下在Linux下各环境的搭建,主要就讲一下jdk.MySQL.和一个代理服务器nginx 1. jdk的安装配置 1)卸载自带openjdk 当我们拿到一个全新的ECS的时候上面有的会自带 ...
- 深入理解Redis(一)——高级键管理与数据结构
引语 这个章节主要讲解了三部分内容: 如何设计并管理Redis的键以及与其关联的数据结构: 了解并使用Redis客户端对象映射器: 介绍如何利用大O标记来评估Redis性能. 键与数据结构 键 我们先 ...
- 树莓派-基于raspivid实现拍视频
经过上一篇<<树莓派-安装摄像头模块>>之后 想要用摄像头模块拍一段视频的话,可以从命令行运行 raspivid 工具.下面这句命令会按照默认配置(长度5秒,分辨率1920x1 ...