You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

停止Spring JMS监听器在ActiveMQ Classic中引发异常行为

问题场景与现象

代码实现

JMS监听器定义

@JmsListener(id="myid", destination = "myDestination")
public void SampleJmsListenerMethod(String text) {
    System.out.println("1: "+text);
}

@JmsListener(id="myid2", destination = "myDestination")
public void SampleJmsListenerMethod2(String text) {
    System.out.println("2: "+text);
}

启停控制REST接口

@RequestMapping(value="/halt", method= RequestMethod.GET)
public @ResponseBody
String haltJmsListener() {
    JmsListenerEndpointRegistry customRegistry =
            context.getBean(JmsListenerEndpointRegistry.class);
    Objects.requireNonNull(customRegistry.getListenerContainer("myid")).stop();
    return "Jms Listener Stopped";
}

@RequestMapping(value="/restart", method=RequestMethod.GET)
public @ResponseBody
String reStartJmsListener() {
    JmsListenerEndpointRegistry customRegistry =
            context.getBean(JmsListenerEndpointRegistry.class);
    Objects.requireNonNull(customRegistry.getListenerContainer("myid")).start();
    return "Jms Listener restarted";
}

观测到的行为

  • 应用启动后:存在2个连接、2个活跃消费者,消息以轮询方式被两个监听器消费。
  • 停止myid监听器后:控制台仍显示2个连接和消费者,但仅能收到每隔1条的消息,其余消息滞留在队列中。
  • 重启myid监听器后:会先消费积压的消息,之后恢复轮询消费。
  • 版本差异:
    • 问题复现版本:ActiveMQ Classic 5.15(搭配Spring 2.3.12)、5.16(搭配Spring 2.7.8)
    • 正常表现版本:Spring 3.2.1 + ActiveMQ 5.18,停止监听器后剩余监听器会消费所有消息,且对应连接会被移除。

疑问

该旧版本中的异常行为是否属于预期情况?


结论

这种旧版本中的行为不属于预期情况,是Spring JMS和ActiveMQ Classic旧版本组合下的实现缺陷:

  • 在旧版本中,调用stop()方法停止监听器容器时,Spring JMS并未正确关闭对应JMS连接和消费者,导致ActiveMQ端仍认为该消费者存在,依旧会将消息分发给这个已失效的消费者,从而造成消息滞留。
  • Spring 3.x+和ActiveMQ 5.18的组合中,Spring JMS优化了监听器容器停止时的资源清理逻辑,同时ActiveMQ也完善了消费者失效的检测机制,能够正确移除失效的消费者连接,剩余消费者会接管所有消息的消费,这才是符合预期的行为。

内容的提问来源于stack exchange,提问作者Pieter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 03:33:18