记一次CLOSE_WAIT多的故障

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记一次CLOSE_WAIT多的故障相关的知识,希望对你有一定的参考价值。

问题:

Cannot send, channel has already failed: tcp://ip:61616
javax.jms.JMSException: Cannot send, channel has already failed: tcp://ip:61616

应用连不上mq

解决方案:

一,分析思路:

1.现象:通过netstat 查看与61616相关的连接状况,发现130多个CLOSE_WAIT

2.是什么原因造成这么多的CLOSE_WAIT?

2.1 主要原因是某种情况下应用关闭了socket连接,但是mq忙于读或者写,没有关闭连接.

2.2 代码需要判断socket,一旦读到0,断开连接,read返回负,检查一下errno,如果不是AGAIN,就断开连接。

3.造成CLOSE_WAIT之后服务为啥连不上mq呢?

linux分配给一个用户的文件句柄是有限的,CLOSE_WAIT状态一直被保持,意味着对应数目的通道就一直被占着,一旦达到句柄数上线,新的请求就无法被处理了,应用程序可能会返回大量的Too many openfiles异常.

4.什么是CLOSE_WAIT?

4.1 mq为被连接端,java服务为主动方,在被动关闭情况下,mq已经接收到FIN,但是还没有发送自己的FIN的时刻,连接处于CLOSE_WAIT状态;

二,解决办法:

1.重启mq

2,linux下设置如下三个参数:

/proc/sys/net/ipv4/tcp_keepalive_time当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时。

/proc/sys/net/ipv4/tcp_keepalive_intvl当探测没有确认时,重新发送探测的频度。缺省是75秒。

/proc/sys/net/ipv4/tcp_keepalive_probes在认定连接失效之前,发送多少个TCP的keepalive探测包。缺省值是9。这个值乘以tcp_keepalive_intvl之后决定了,一个连接发送了keepalive之后可以有多少时间没有回应。

三.了解扩展

1.客户端先发送FIN,进入FIN_WAIT1状态

服务端收到FIN,发送ACK,进入CLOSE_WAIT状态,客户端收到这个ACK,进入FIN_WAIT2状态
服务端发送FIN,进入LAST_ACK状态
客户端收到FIN,发送ACK,进入TIME_WAIT状态,服务端收到ACK,进入CLOSE状态
客户端TIME_WAIT持续2倍MSL时长,在linux体系中大概是60s,转换成CLOSE状态

2.服务端使用的短链接,每次客户端请求后,服务端都会主动发送FIN关闭连接.最后进入到time_wait状态.对于访问量大的web server,会存在大量的TIME_WAIT状态.让服务器能够快速回收和重用那些TIME_WAIT的资源,可修改内核参数.

修改/etc/sysctl.conf如下:
#对于一个新建连接,内核要发送多少个 SYN 连接请求才决定放弃,不应该大于255,默认值是5,对应于180秒左右时间
net.ipv4.tcp_syn_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
修改完之后执行/sbin/sysctl -p让参数生效。

相关文章:
http://vinc.top/2016/08/22/time_wait%E5%92%8Cclose_wait%E4%BA%A7%E7%94%9F%E5%8E%9F%E5%9B%A0%E5%8F%8A%E8%A7%A3%E5%86%B3/

以上是关于记一次CLOSE_WAIT多的故障的主要内容,如果未能解决你的问题,请参考以下文章

记一次启动故障

记一次无法远程故障排查20161211.2111

记一次kafka故障

记一次Raid故障磁盘故障恢复

解Bug之路-记一次存储故障的排查过程

Mongodb---记一次事故故障