欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ActiveMQ连接不释放问题

程序员文章站 2022-03-10 13:01:13
...

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后,服务器确实能够检查到连接的断开.

强制断开的连接不会被检测到断开?

实际上这个猜想是正确的,但实验手段存在问题.

我使用的实验方式如下

  1. telnet a 61615 &
  2. kill -9 pid
  3. 检查连接状态,仍然是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.

观察了两天,没有再次出现这种情况.

实际问题

在上线的时候,记忆恢复了

  1. 一年半前测试过mq在高丢包率下的工作情况,当时设置了40%的丢包率之后,mq也出现了连接未能检测到关闭的情况.
  2. 应用在连接时,直接断开网络,随后关闭应用,再次连接网络,对端无法检测到连接已经关闭,若设置了keepalive则可以在一段时间后检查到连接已经关闭.

也就是所谓的半连接问题,tcp/ip中有专门一章是讲解这个问题的.

知道了问题,反推问题的出现过程就很简单了,设置wireFormat.maxInactivityDuration=0参数后,连接mq,并且在断开之前断开网络,随后恢复网络,便能够复现这种问题.

这个参数默认是30000,即30秒,也就是设置keep-alive为30秒,能够检测到连接失效的情况.

为何没有第一时间想到问题根因

  1. 未进行相关问题的记录,印象不深.
  2. 对tcp/ip还不够熟悉.
  3. 理论情况遇到的不多.
  4. 实验问题的手段需要仔细考虑.
  5. 线上服务器一般不会修改配置,未第一时间检查配置.
相关标签: 各种问题