在启动和停止 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";
}
当应用程序启动时,我看到两个连接和两个活跃的消费者。控制台的输出是:
Sending message to 'myDestination' destination with text hello
1: hello
Sending message to 'myDestination' destination with text hello
2: hello
Sending message to 'myDestination' destination with text hello
1: hello
Sending message to 'myDestination' destination with text hello
2: hello
如果我停止一个监听器,我仍然看到两个连接和两个消费者,但输出突然是:
Sending message to 'myDestination' destination with text hello
Sending message to 'myDestination' destination with text hello
2: hello
Sending message to 'myDestination' destination with text hello
Sending message to 'myDestination' destination with text hello
2: hello
所以我只收到每条消息。其他消息保留在队列中。如果我然后重新启动侦听器,我会得到
1: hello
1: hello
Sending message to 'myDestination' destination with text hello
1: hello
Sending message to 'myDestination' destination with text hello
2: hello
Sending message to 'myDestination' destination with text hello
1: hello
首先是两条消息,已发送但未消费。然后我恢复正常,消息由两个侦听器中的一个循环消耗。
我已经使用 ActiveMQ Classic 5.15 (Spring 2.3.12) 和 5.16 (Spring 2.7.8) 对此进行了测试,并且都表现出了这种行为。
如果我在 Spring 3.2.1 和 5.18 中执行此操作,我不会看到此行为。如果我停止侦听器,所有消息都将进入剩余的侦听器,并且连接将被删除。
有谁知道它是否应该这样工作?
旧版本似乎停止了侦听器,但不释放连接。另请参阅对此答案的评论:https://stackoverflow.com/a/57993175/900119
这解释了我注意到的行为。似乎较新的版本也释放了连接,从而允许 ActiveMQ 将消息重定向到其他消费者。
目前我已经解决了这个问题,不使用 messagelistenercontainer,而仅使用 connectionfactory 并手动创建连接、会话和消息消费者。我可以再次关闭它们,从而产生所需的行为。
PS。 Spring 似乎也有一张票来改变这种行为:https://github.com/spring-projects/spring-framework/issues/30612