ActiveMQ连接不释放问题
ActiveMQ连接不释放问题
实际问题为:大量失效连接处于ESTABLISHED状态.
检查问题的过程
线上出现了activemq连接不上的报错The JMS Connection has failed
到mq所在的服务查看,连接数已经占满了,使用命令
netstat -antp | grep 61615| grep ESTABLISHED| wc -l
获取tcp端口为61615
的ESTABLISHED连接数量,其值已经与activeMQ中配置的maximumConnections=3000一致,所以无法建立新的连接.
查看一下有一台服务器的连接数有2400个,假设这个服务器的ip为a好了,到这台服务器上查看连接数,却发现其与mq的连接仅有2个.
也就是说当前的问题是
源端已经检查到tcp连接的断开,而目的端却未发现连接已经断开
遇事不决,谷歌一下
你遇到的问题,大部分情况下总是有人已经遇到过了的.
如果没有的话,恭喜你.
按照这个问题,去网上搜索activeMQ
是否存在类似的问题,许久无果.
不过这个文档有一些帮助
https://www.jianshu.com/p/a1c3aba4af96
可以查看连接建立的时间.
是否是真实存在的ip?
由于a的服务器ip并非物理ip,即设备上没有这个ip的网卡,怀疑有其他的设备也使用了这个ip来连接mq,因此使用tcpdump监听了一段时间,并没有发现有那些虚假连接的包传输.
使用的命令如下
tcpdump -i eth0 port 61615 and src host a
#其中eth0是使用的网卡,可以通过ip来确认,ip a/ifconfig可以查看网卡的ip.
服务器配置问题?
此时怀疑服务器是否存在什么配置导致其无法检查到tcp连接的断开,于是使用nc -lk
监听了一个新的端口,然后使用服务器a来telnet这个端口,然而关闭telnet后,服务器确实能够检查到连接的断开.
强制断开的连接不会被检测到断开?
实际上这个猜想是正确的,但实验手段存在问题.
我使用的实验方式如下
- telnet a 61615 &
- kill -9 pid
- 检查连接状态,仍然是time-wait
linux下,进程销毁后,其相关的资源将会被全部释放
然而在排查问题的当时,并未想到这个关键点,也由此导致了后面的弯路.
MQ的问题?
现网的mq版本和本地的mq版本是一致的,所以可以使用本地的mq来进行测试.
检查了创建连接的代码后发现仅关闭了connection而未关闭session,因此编写了一个简单的连接product来进行测试,然而并不存在这种问题.
检查了现网和本地的mq配置后,发现现网的配置多了一条wireFormat.maxInactivityDuration=0
搜索了一下这个参数,找到了下面这篇文章
https://blog.csdn.net/tcdpyh6sa3/article/details/60960434
由此猜测是由该配置引发的问题.
于是在本地进行相应的测试,然而在调用connection.close
后,服务端仍然能够发现连接已经关闭.
恢复
由于现网情况,无法随意重启,并且部分业务仍然在正常运行,只有一个新上线的业务无法连接到mq,因此申请了上线后去除了该参数,并重启了mq.
观察了两天,没有再次出现这种情况.
实际问题
在上线的时候,记忆恢复了
- 一年半前测试过mq在高丢包率下的工作情况,当时设置了40%的丢包率之后,mq也出现了连接未能检测到关闭的情况.
- 应用在连接时,直接断开网络,随后关闭应用,再次连接网络,对端无法检测到连接已经关闭,若设置了keepalive则可以在一段时间后检查到连接已经关闭.
也就是所谓的半连接问题,tcp/ip中有专门一章是讲解这个问题的.
知道了问题,反推问题的出现过程就很简单了,设置wireFormat.maxInactivityDuration=0参数后,连接mq,并且在断开之前断开网络,随后恢复网络,便能够复现这种问题.
这个参数默认是30000,即30秒,也就是设置keep-alive为30秒,能够检测到连接失效的情况.
为何没有第一时间想到问题根因
- 未进行相关问题的记录,印象不深.
- 对tcp/ip还不够熟悉.
- 理论情况遇到的不多.
- 实验问题的手段需要仔细考虑.
- 线上服务器一般不会修改配置,未第一时间检查配置.