服务器TIME_WAIT和CLOSE_WAIT分析和解决办法
先上两张图:
查看TIME_WAIT和CLOSE_WAIT数的命令:
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
它会显示例如下面的信息:
TIME_WAIT 、CLOSE_WAIT 、FIN_WAIT1 、ESTABLISHED 、SYN_RECV 、LAST_ACK 常用的三个状态是:ESTABLISHED表示正在通信 、TIME_WAIT表示主动关闭、CLOSE_WAIT表示被动关闭。
服务器出现异常最长出现的状况是:
- 服务器保持了大量的TIME_WAIT状态。
- 服务器保持了大量的CLOSE_WAIT状态。
我们也都知道Linux系统中分给每个用户的文件句柄数是有限的,而TIME_WAIT和CLOSE_WAIT这两种状态如果一直被保持,那么意味着对应数目的通道(此处应理解为socket,一般一个socket会占用服务器端一个端口,服务器端的端口最大数是65535)一直被占用,一旦达到了上限,则新的请求就无法被处理,接着就是大量Too Many Open Files异常,然后tomcat、nginx、apache崩溃。。。
下面来讨论这两种状态的处理方法,网络上也有很多资料把这两种情况混为一谈,认为优化内核参数就可以解决,其实这是不恰当的。优化内核参数在一定程度上能解决time_wait过多的问题,但是应对close_wait还得从应用程序本身出发。
服务器保持了大量的time_wait状态
这种情况比较常见,一般会出现在爬虫服务器和web服务器(如果没做内核参数优化的话)上,那么这种问题是怎么产生的呢?
从上图可以看出time_wait是主动关闭连接的一方保持的状态,对于爬虫服务器来说它自身就是客户端,在完成一个爬取任务后就会发起主动关闭连接,从而进入time_wait状态,然后保持这个状态2MSL时间之后,彻底关闭回收资源。这里为什么会保持资源2MSL时间呢?这也是TCP/IP设计者规定的。
TCP要保证在所有可能的情况下使得所有的数据都能够被正确送达。当你关闭一个socket时,主动关闭一端的socket将进入TIME_WAIT状 态,而被动关闭一方则转入CLOSED状态,这的确能够保证所有的数据都被传输。当一个socket关闭的时候,是通过两端四次握手完成的,当一端调用 close()时,就说明本端没有数据要发送了。这好似看来在握手完成以后,socket就都可以处于初始的CLOSED状态了,其实不然。原因是这样安排状态有两个问题, 首先,我们没有任何机制保证最后的一个ACK能够正常传输,第二,网络上仍然有可能有残余的数据包(wandering duplicates),我们也必须能够正常处理。
TIMEWAIT就是为了解决这两个问题而生的。
- 假设最后的一个ACK丢失,那么被动关闭一方收不到这最后一个ACK则会重发FIN。此时主动关闭一方必须保持一个有效的(time_wait状态下维持)状态信息,以便可以重发ACK。如果主动关闭的socket不维持这种状态而是进入close状态,那么主动关闭的一方在收到被动关闭方重新发送的FIN时则响应给被动方一个RST。被动方收到这个RST后会认为此次回话出错了。所以如果TCP想要完成必要的操作而终止双方的数据流传输,就必须完全正确的传输四次握手的四步,不能有任何的丢失。这就是为什么在socket在关闭后,任然处于time_wait状态的第一个原因。因为他要等待可能出现的错误(被动关闭端没有接收到最后一个ACK),以便重发ACK。
- 假设目前连接的通信双方都调用了close(),双方同时进入closed的终结状态,而没有走 time_wait状态。则会出现如下问题:假如现在有一个新的连接建立起来,使用的IP地址与之前的端口完全相同,现在建立的一个连接是之前连接的完全复用,我们还假定之前连接中有数据报残存在网络之中,这样的话现在的连接收到的数据有可能是之前连接的报文。为了防止这一点。TCP不允许新的连接复用time_wait状态下的socket。处于time_wait状态的socket在等待2MSL时间后(之所以是两倍的MSL,是由于MSL是一个数据报在网络中单向发出 到认定丢失的时间,即(Maximum Segment Lifetime)报文最长存活时间,一个数据报有可能在发送途中或是其响应过程中成为残余数据报,确认一个数据报及其响应的丢弃需要两倍的MSL),将会转为closed状态。这就意味着,一个成功建立的连接,必须使得之前网络中残余的数据报都丢失了。
再引用网络中的一段话:
- 值得一说的是,基于TCP的http协议,一般(此处为什么说一般呢,因为当你在keepalive时间内 主动关闭对服务器端的连接时,那么主动关闭端就是客户端,否则客户端就是被动关闭端。下面的爬虫例子就是这种情况)主动关闭tcp一端的是server端,这样server端就会进入time_wait状态,可想而知,对于访问量大的web服务器,会存在大量的time_wait状态,假如server一秒钟接收1000个请求,那么就会积压240*1000=240000个time_wait状态。(RFC 793中规定MSL为2分钟,实际应用中常用的是30秒,1分钟和2分钟等。),维持这些状态给服务器端带来巨大的负担。当然现代操作系统都会用快速的查找算法来管理这些 TIME_WAIT,所以对于新的 TCP连接请求,判断是否hit中一个TIME_WAIT不会太费时间,但是有这么多状态要维护总是不好。
- HTTP协议1.1版本规定default行为是keep-Alive,也就是会重用tcp连接传输多个 request/response。之所以这么做的主要原因是发现了我们上面说的这个问题。
服务器保持了大量的close_wait状态:
time_wait问题可以通过调整内核参数和适当的设置web服务器的keep-Alive值来解决。因为time_wait是自己可控的,要么就是对方连接的异常,要么就是自己没有快速的回收资源,总之不是由于自己程序错误引起的。但是close_wait就不一样了,从上图中我们可以看到服务器保持大量的close_wait只有一种情况,那就是对方发送一个FIN后,程序自己这边没有进一步发送ACK以确认。换句话说就是在对方关闭连接后,程序里没有检测到,或者程序里本身就已经忘了这个时候需要关闭连接,于是这个资源就一直被程序占用着。这个时候快速的解决方法是:
- 关闭正在运行的程序,这个需要视业务情况而定。
- 尽快的修改程序里的bug,然后测试提交到线上服务器。
注:
直到写这篇文章的时候我才完全弄明白之前工作中遇到的一个问题。程序员写了爬虫(php)运行在采集服务器A上,程序去B服务器上采集资源,但是A服务器很快就发现出现了大量的close_wait状态的连接。后来手动检查才发现这些处于close_wait状态的请求结果都是404,那就说明B服务器上没有要请求的资源。
下面引用网友分析的结论:
服 务器A是一台爬虫服务器,它使用简单的HttpClient去请求资源服务器B上面的apache获取文件资源,正常情况下,如果请求成功,那么在抓取完 资源后,服务器A会主动发出关闭连接的请求,这个时候就是主动关闭连接,服务器A的连接状态我们可以看到是TIME_WAIT。如果一旦发生异常呢?假设 请求的资源服务器B上并不存在,那么这个时候就会由服务器B发出关闭连接的请求,服务器A就是被动的关闭了连接,如果服务器A被动关闭连接之后程序员忘了 让HttpClient释放连接,那就会造成CLOSE_WAIT的状态了。
服务器TIME_WAIT和CLOSE_WAIT分析和解决办法的更多相关文章
- 一次TIME_WAIT和CLOSE_WAIT故障和解决办法
昨天解决了一个curl调用错误导致的服务器异常,具体过程如下: 里头的分析过程有提到,通过查看服务器网络状态检测到服务器有大量的CLOSE_WAIT的状态. 在服务器的日常维护过程中,会经常用到下面的 ...
- 服务器TIME_WAIT和CLOSE_WAIT详解和解决办法
转载的服务器TIME_WAIT和CLOSE_WAIT详解和解决办法
- JavaScript中的ParseInt("08")和“09”返回0的原因分析及解决办法
今天在程序中出现一个bugger ,调试了好久,最后才发现,原来是这个问题. 做了一个实验: alert(parseInt("01")),当这个里面的值为01====>07时 ...
- php中session_start()相关问题分析与解决办法
介绍下,在php中使用session时遇到的一些问题,与相关解决方法.1.错误提示Warning: Cannot send session cookie - headers already sentW ...
- oracle执行update语句时卡住问题分析及解决办法
转载:http://www.jb51.net/article/125754.htm 这篇文章主要介绍了oracle执行update语句时卡住问题分析及解决办法,涉及记录锁等相关知识,具有一定参考价值, ...
- HTML5服务器推送消息的各种解决办法,html5服务器
HTML5服务器推送消息的各种解决办法,html5服务器 摘要 在各种BS架构的应用程序中,往往都希望服务端能够主动地向客户端推送各种消息,以达到类似于邮件.消息.待办事项等通知. 往BS架构本身存在 ...
- selenium元素定位不到问题分析及解决办法
最近正在学习写自动化测试脚本,遇到一个错误迟迟未解决,导致自信心大受挫败,甚至想放弃. 思考许久突然想到,我遇到的问题是否也有人会遇到,如果有的话问题就应该有解决办法了.没什么问题是百度解决不了的,如 ...
- 服务器CPU使用率高的原因分析与解决办法
我们的服务器在使用操作系统的时候,用着用着系统就变慢了,打开“ 任务管理器 ”一看,才发现CPU使用率达到80%以上.这是怎么回事情呢?遇到病毒了吗?硬件有问题?还是系统设置有问题呢?在本文中将从硬件 ...
- Nested Loops join时显示no join predicate原因分析以及解决办法
本文出处:http://www.cnblogs.com/wy123/p/6238844.html 最近遇到一个存储过程在某些特殊的情况下,效率极其低效, 至于底下到什么程度我现在都没有一个确切的数据, ...
随机推荐
- 使用JSONPath
SONPath是查询JSON对象元素的标准方法.JSONPath使用路径表达式来导航JSON文档中的元素,嵌套元素和数组.有关JSON的更多信息,请参阅JSON简介. 使用JSONPath访问JSON ...
- A Simple Math Problem (矩阵快速幂)
Lele now is thinking about a simple function f(x). If x < 10 f(x) = x. If x >= 10 f(x) = a0 ...
- centOS6.5 安装后无法启动无线上网
查看无线网卡型号:[root@mookee rtl8192se_linux_2.6.0019.1207.2010]# lspci |grep Network03:00.0 Network contro ...
- ORA-06502 when awr report produce
最近在生成一套系统的AWR报告时出现了如下报错:ORA-06502: PL/SQL: numeric or value error: character string buffer too small ...
- Qt5.7中使用MySQL Driver(需要把libmysql.dll文件拷贝到Qt的bin目录中。或者自己编译的时候,链接静态库)
Qt5.7中使用MySQL Driver 1.使用环境 Qt5.7的安装安装就已经带了MySQL Driver,只需要在安装的时候选择一下即可.如果没有安装,可以采取自己编译的方式.在Qt的源码包的q ...
- 解读 iostat -mxd 1
#### for AWR 报告 : 建议如下: 不能随便调整db_file_multiblock_read_count 值, 取同样时间段的AWR 报告 02:00 ~ 05:00,所以db_file ...
- 从I/O事件到阻塞、非阻塞、poll到epoll的理解过程
I/O事件 I/O事件 非阻塞I/O.在了解非阻塞I/O之前,需要先了解I/O事件 我们知道,内核有缓冲区.假设有两个进程A,B,进程B想读进程A写入的东西(即进程A做写操作,B做读操作).进程A ...
- 关于 SQL Server Reporting Services 匿名登录的解决方案
每次访问报表都需要windows验证,这样的报表给客户确实很说不过去. SSRS 可以匿名登录的设定步骤: 环境: 开发工具:SQL Server Business Intelligence Deve ...
- java 与 c#的 中 字符串比较“==”与“equals”的差异
.net中,其字符串特有的驻留机制,保证了在同一进程中,相同字符序列的字符串,只有一个实例,这样能避免相同内容的字符串重复实例化,以减少性能开销. 先来回顾一下c#中的代码: public stati ...
- $.ajax同步/异步(async:false/true)
虽然说ajax用来执行异步请求的比较多,但有时还是存在需要同步执行的情况的. 比如:我需要通过ajax取执行请求以返回一个值,这个值在ajax后面是需要使用到的,这时就不能用异步请求了.这时候就需要使 ...