假设您有两个在不同VM上启动的Spring DefaultMessageListenerContainer
监听同一队列(例如ActiveMQ)。
发送1 000 000条消息。500000条消息后,您希望其余消息仅由一个DefaultMessageListenerContainer
处理,但不调用另一个的destroy或shutdown(因为将来可能需要它-并且必须保留它可以通过JMX进行管理)。这些数字仅是此处的示例,应该忽略,可以替换为“一段时间后,某些消息后等等”。
这听起来很简单:在另一个DefaultMessageListenerContainer
上停止呼叫。错误的,因为消息是以循环方式发送的,并且已在消费者中注册。
添加事务支持并在每次收到消息时在第二个DefaultMessageListenerContainer
中引发错误,它将被第一个消息回滚并采用(循环)。再次错误,消息以某种方式向使用者注册,不允许第一个DefaultMessageListenerContainer
接收消息。
即使您关闭/销毁了第一个DMLC,该消息也不会被另一个DMLC使用。仅当我杀死了正在运行的已关闭/销毁的DMLC的JVM时,它们才被消耗。
到目前为止,我的解决方案:由于Session.AUTO_ACKNOWLEDGE
消息在进入DefaultMessageListenerContainer
的MessageListener中的onMessage方法之前已从队列中取出。在MessageListener
中实现SessionAwareMessageListener
并重新发送具有相同有效负载的消息的新副本。
但这看起来真的很脏-我希望我可以以“ JMS”式的方式做更多的事情。
最佳答案
我没有完全掌握这一部分:“ [消息]已在消费者那里注册”。您是说ActiveMQ决定将其发送给哪个侦听器吗?当您在DMLC上呼叫“停止”时,会发生什么情况?
我不知道这是否可以克服您的困难,但这是一个主意:DMLC中的消息选择器是活动的:您可以随时更改它们,并且它们立即生效。也许尝试将消息选择器更改为“ FALSE”;所有缓存的消息都应完成处理,而新的消息应停止出现。