2018年6月,我们开发了两个使用Artemis作为消息队列的信用模块和PUSH推送模块。经过几轮测试,大家满怀信心地正式上线了。而且经过一个多月的使用,一切都很顺利,感觉生活中的一切都是美好的。问题是2018年8月来的,前一天突然传来一个坏消息。用户注册后未获得积分。这真是一个打击。但是,我不能因为一次打击就失去对Artemis的信任,所以我对整个模块进行了代码分析,发现代码没问题,好吧!分析问题,查看Artemis控制台,发现有很多未消费的消息。之前一个多月没问题,也没有未消费的消息,中间做了升级。仔细分析所有证据后,我断定这是一起由重启引发的“血案”!如果某个Artemis节点上有很多未消费的消息,而且还在增加,那么只有一种可能。本节点上没有消费者连接,本节点上的消息无法重新分发到其他节点。既然这样,问题就很清楚了。向上。为什么生产者在这个节点上没有消费者连接时一直在发送消息?一般情况下,只有Consumer会向节点发送消息。这个在测试环境是不存在的,如果没有consumer的消息应该会重新分发到其他节点,所以我推测是Artemis集群有问题,查看Artemis生产中61616端口的链接环境更多TIME_WAIT。所以我做了如下两个调整:修改linux网络配置,修改linux网络配置,减少TIME_WAIT连接数,减少断线识别时间。具体操作步骤如下:打开文件/etc/sysctl.conf,编辑文件,添加如下内容:net.ipv4.tcp_syncookies=1net.ipv4.tcp_tw_reuse=1net.ipv4.tcp_tw_recycle=1net.ipv4.tcp_fin_timeout=30然后执行/sbin/sysctl-p使参数生效。修改Artemis集群模式我将Artemis集群从UDP更改为静态集群模式。上面的修改保证了客户端连接可以快速断开,应用重启的时候不会一直往这里发送消息。我使用jmeter进行压力测试。在重启消费者的过程中,消息重分发是正常的。SpringJms的坑完美吗?不!发现一个新问题。在50线程压力测试期间重新启动应用程序。重启后虽然消息消费和重分发正常,但是在重启的瞬间,服务端判断消费者在ON_DEMAND模式的节点上断开连接时有一部分延迟。有些消息被发送到没有消费者的节点,这些消费者不能再被重新分配。这可能是Artemis中的一个错误。怎么做?为什么一个应用只能连接一个节点?这不能说是spring-jms的坑,或者spring-jms不够用。spring-jms创建消费监听时,不管有多少Session,它只会创建一个共享连接,不管你有多少Artemis。节点,一个应用永远只会连接到一个节点上,真的是一个很大的浪费。这真是SpringJms的坑。自己动手,丰衣足食阿尔忒弥斯真的有那么糟糕吗?其实看了Artemis自带的client后,发现其实在创建连接的时候自带了三种策略。一种是轮询,适用于对性能要求比较高的场景,提高消费效率。一种是随机的,随便选一个节点去连接,不知道为什么会有这样的策略。一种是只取第一个节点,适用于双机热备场景。所以SpringJms带来的坑还得自己去填,内置的客户端用于创建消费者监听器。在这种情况下,只要最大连接数超过2个或更多,并且通过轮询创建连接,就会创建平均连接数。在一个节点上,即使在重启过程中有几条消息无法重新分发,消费者也可以在重启后继续消费。好了,大功告成,生活终于又美好了。
