手机版
你好,游客 登录 注册
背景:
阅读新闻

记一次大量CLOSE_WAIT的解决方案

[日期:2019-08-26] 来源:Linux社区  作者:Linux [字体: ]

问题:

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让参数生效。

Linux公社的RSS地址https://www.linuxidc.com/rssFeed.aspx

本文永久更新链接地址https://www.linuxidc.com/Linux/2019-08/160357.htm

linux
相关资讯       CLOSE_WAIT  大量CLOSE_WAIT 
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款