文章目录

  • 解决方法1
    • 疑问:tcp_tw_reuse如何打开?要编译linux内核?
  • 解决方法2:优化程序,减少TCP链接的创建与关闭,同一台服务器,连接一次就好了,不要连接了又关闭,然后再连接
    • 相应缩写
    • 一、TCP 状态示意图
    • 二、查询TCP连接数可以使用下面的Linux netstat命令
    • 三、服务器出现异常最长出现的状况是:
    • 四、服务器保持了大量的time_wait状态
    • 五、服务器保持了大量的close_wait状态
    • 六、HttpClient未释放连接,将会造成CLOSE_WAIT的状态
  • 参考文章

解决方法1

tcp_tw_reuse 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭 tcp_tw_recycle 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭
对于客户端

  1. 作为客户端因为有端口65535问题,TIME_OUT过多直接影响处理能力,打开tw_reuse 即可解决,不建议同时打开tw_recycle,帮助不大;
  2. tw_reuse 帮助客户端1s完成连接回收,基本可实现单机6w/s短连接请求,需要再高就增加IP数量; 3. 如果内网压测场景,且客户端不需要接收连接,同时 tw_recycle 会有一点点好处; 4. 业务上也可以设计由服务端主动关闭连接。 不像客户端有端口限制,处理大量TIME_WAIT Linux已经优化很好了,每个处于TIME_WAIT 状态下连接内存消耗很少, 而且也能通过tcp_max_tw_buckets = 262144 配置最大上限,现代机器一般也不缺这点内存。 粗暴点的话 直接发rst要是对数据可靠性没什么要求的话

疑问:tcp_tw_reuse如何打开?要编译linux内核?

tcp_tw_reuse可在客户端打开,服务端不用打开

tcp_tw_reuse仅在TCP套接字作为客户端,调用connect时起作用。绝大部分的TCP服务器,应该不会有大量主动连接的动作(或许会连接DB等,但一般也是长连接)。因此这个选项对于TCP服务来说,基本上是无用的,完全是没必要打开

解决方法2:优化程序,减少TCP链接的创建与关闭,同一台服务器,连接一次就好了,不要连接了又关闭,然后再连接

这边直接转载一篇文章吧:服务器TIME_WAIT和CLOSE_WAIT分析和解决办法

相应缩写

SYN:SYNchronize(同步)
ACK:ACKnowledge character(确认字符)
FIN:FINish(终止)
MSL:Maximum Segment Life(最大分段寿命)
RST:Reset(重置)

一、TCP 状态示意图


二、查询TCP连接数可以使用下面的Linux netstat命令

netstat -ant|awk '/^tcp/ {++state[$NF]} END {for(key in state) print (key,state[key])}'

我们hikflow_demo程序启动后:(果然程序有问题啊,这么多TIME_WAIT的。。。)
(启动后)

# netstat -ant|awk '/^tcp/ {++state[$NF]} END {for(key in state) print (key,state[key])}'
LISTEN 8
FIN_WAIT2 1
ESTABLISHED 3
SYN_SENT 45
CLOSE_WAIT 1
TIME_WAIT 11

(过了一段时间)

# netstat -ant|awk '/^tcp/ {++state[$NF]} END {for(key in state) print (key,state[key])}'
LISTEN 8
ESTABLISHED 4
CLOSE_WAIT 1
TIME_WAIT 111

(关闭程序后)

# netstat -ant|awk '/^tcp/ {++state[$NF]} END {for(key in state) print (key,state[key])}'
LISTEN 8
FIN_WAIT2 1
ESTABLISHED 3
TIME_WAIT 95

(关闭程序后过一段时间,可以看到TIME_WAIT不断减少,最终降为2)

# netstat -ant|awk '/^tcp/ {++state[$NF]} END {for(key in state) print (key,state[key])}'
LISTEN 8
ESTABLISHED 4
TIME_WAIT 2

常用的三个状态是:ESTABLISHED表示正在通信 、TIME_WAIT表示主动关闭、CLOSE_WAIT表示被动关闭。

三、服务器出现异常最长出现的状况是:

(1)服务器保持了大量的TIME_WAIT状态。
(2)服务器保持了大量的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),我们也必须能够正常处理。

TIME_WAIT就是为了解决这两个问题而生的。

假设最后的一个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以确认。换句话说就是在对方关闭连接后,程序里没有检测到,或者程序里本身就已经忘了这个时候需要关闭连接,于是这个资源就一直被程序占用着。这个时候快速的解决方法是:
(1)关闭正在运行的程序,这个需要视业务情况而定。
(2)尽快的修改程序里的bug,然后测试提交到线上服务器。

六、HttpClient未释放连接,将会造成CLOSE_WAIT的状态

某爬虫程序运行在采集服务器A上,然后去B服务器上采集资源,但是A服务器很快就发现出现了大量的close_wait状态的连接。后来手动检查才发现这些处于close_wait状态的请求结果都是404,那就说明B服务器上没有要请求的资源。

之所以出现close_wait,是因为:

服务器A是一台爬虫服务器,它使用简单的HttpClient去请求资源服务器B上面的apache获取文件资源,正常情况下,如果请求成功,那么在抓取完资源后,服务器A会主动发出关闭连接的请求,这个时候就是主动关闭连接,服务器A的连接状态我们可以看到是TIME_WAIT。如果一旦发生异常呢?假设请求的资源服务器B上并不存在,那么这个时候就会由服务器B发出关闭连接的请求,服务器A就是被动的关闭了连接,如果服务器A被动关闭连接之后程序员忘了让HttpClient释放连接,那就会造成CLOSE_WAIT的状态了。

参考文章

参考文章1:解决TIME_WAIT过多造成的问题

参考文章2:netstat命令 stat状态说明

参考文章3:怎么解决socket短链接存在大量TIME_WAIT问题? - 知乎

参考文章4:服务器TIME_WAIT和CLOSE_WAIT分析和解决办法

如何解决 linux socket TIME_WAIT 过多造成的问题(SYN、ACK、FIN、MSL、RST含义)netstat查看TCP连接数命令相关推荐

  1. Linux查看tcp连接数

    1 查看所有tcp连接数 netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' 或者(效果等同) netstat - ...

  2. Linux socket TIME_WAIT 优化

    如发现系统存在大量TIME_WAIT状态的连接,通过调整内核参数解决, vim /etc/sysctl.conf 编辑文件,加入以下内容: net.ipv4.tcp_syncookies = 1 ne ...

  3. 树莓派安装FFTW,linux安装库不生成.so库,拷贝.so .a,按时间查看文件的命令

    目录 1.树莓派安装FFTW 2.不生成.so库的问题 3.从.a生成.so 4.直接复制.so .a 5.按时间查看文件 1.树莓派安装FFTW 树莓派安装fftw_zhangjun62的博客-CS ...

  4. linux 查看当前连接ip,netstat查看系统连接数及当前连接IP

    1.查看当前连接IP地址: [root@centos69 ~]#netstat -nat Active Internet connections (servers and established) P ...

  5. 查看linux中的TCP连接数

    一.查看哪些IP连接本机 netstat -an 二.查看TCP连接数 1)统计80端口连接数 netstat -nat|grep -i "80"|wc -l 2)统计httpd协 ...

  6. Linux查看网络连接数,统计网络连接数(netstat、Apache连接数)

    一.查看哪些IP连接本机 netstat -an 二.查看TCP连接数 1)统计80端口连接数 netstat -nat|grep -i "80"|wc -l 2)统计httpd协 ...

  7. 查看linux中tcp连接数

    一.查看哪些IP连接本机 netstat -an 二.查看TCP连接数 1)统计80端口连接数 netstat -nat|grep -i "80"|wc -l 2)统计httpd协 ...

  8. linux查看ssh连接数,查看linux中的TCP连接数

    一.查看哪些IP连接本机 netstat -an 二.查看TCP连接数 1)统计80端口连接数 netstat -nat|grep -i "80"|wc -l 2)统计httpd协 ...

  9. Linux:Nginx高并发之服务器最大TCP连接数及调优汇总(转载)

    Linux TCP连接数优化及调优 启动线程数: 启动线程数=[任务执行时间/(任务执行时间-IO等待时间)]*CPU内核数 最佳启动线程数和CPU内核数量成正比,和IO阻塞时间成反比.如果任务都是C ...

最新文章

  1. C#计算两个日期的相隔天数
  2. [leetcode]Multiply Strings @ Python
  3. SQL2K数据库开发二十六之存储过程操作创建存储过程(一)
  4. 火狐 增强查找工具栏_在“提示”框中:简单的IE至Firefox同步,轻松的Windows工具栏和识别USB电缆...
  5. django与easyui使用过程中遇到的问题
  6. 用鼠标选择模型表面两点并连线
  7. opencv-api drawKeypoints drawMatches
  8. 利用nginx 反向代理解决跨域问题
  9. 数据结构(主席树):HZOI 2016 采花
  10. Ajax学习笔记-get请求参数-4
  11. CNDS 签到在哪里
  12. 计算机知识脑筋急转弯,10道智力题图片及答案大全|2018年朋友圈最烧脑的10道智力题 附答案_最火软件站...
  13. 3D打印技术让实现更多天马行空的创意
  14. 英语计算机四级如何查询,四级成绩查询
  15. ZYNQ的Linux Linaro系统镜像制作SD卡启动
  16. 双色OLED屏图片点阵转换工具(OledTools)
  17. tinyproxy王卡免流配置_【免流教程】王卡动态tiny免流教程
  18. 卡通鱼(cartoon fish)
  19. 深入理解操作系统实验——bomb lab(phase_2)
  20. vue药物管理系统nodejs

热门文章

  1. 20个数据库设计的最佳实践
  2. 天使投资家李镇樟:如何培养世界级企业家
  3. SAP Business Area 业务范围
  4. ETL工具大全,你了解多少
  5. SAP 如何定义后台job
  6. 如何确定固定资产入账价值
  7. SAP成本收集器两则
  8. 做总账凭证FB50报错“错误调用功能模块 CHECK_PLANTS_ABROAD_ACTIVE”
  9. 2021年有不加班的选择吗?哪些城市加班最严重?
  10. 安徽工程大学C语言程序设计实验报告,安徽工业大学嵌入式实验报告.docx