我有一个要求,我目前还不知道是否有可能。如果消息包含指定的属性,我想临时禁用JMS消息的devliery。目前我正在使用HornetQ作为消息提供者。
我们举个例子:
队列包含以下三个条目:
{1, "foo", "A_CATEGORY"}
{2, "bar", "B_CATEGORY"}
{9, "bof", "A_CATEGORY"}
在某个时刻,应用程序必须能够告诉HornetQ消息服务器此时不应传递属于B_CATEGORY的消息(例如,因为B_CATEGORY对象的底层数据库得到更新)。因此,id为2的消息此时将不会被传递,而1和9将被传递,因为它们具有类别对象的不同值。
必须在没有重新启动应用程序的情况下从Java代码中发生。这有可能吗?
感谢您的帮助!
想到这个问题的替代设计方法。假设第一个Queue包含具有所有类别的消息(顺便说一下,不可能为每个类别创建一个队列,因为可能有很多类别)。正常配置该“正常”队列(例如,没有到期,但是DLQ)。
现在,如果侦听器使用此类消息并发现它无法处理属于某个类别的消息,则会将其置于第二个队列中。此队列配置了重新传递延迟以及到期时间。如果现在设置的到期时间足够高(当然不是队列溢出)并且重新传递时间不会太短,那么如果没有上述问题的解决方案,这应该可以解决。
当然,必须计算在无法处理类别期间可以创建多少个队列条目。还有一个类别的可用性可以持续多长时间,以便可以相应地调整重新发送。
答案 0 :(得分:1)
据我所知,消息驱动bean无法实现。
使用标准JMS使用者可以实现类似的功能:
MessageConsumer c = session.createConsumer(destination);
while ( b-category-can-be-processed ) {
Message m = c.receive();
// process messages until b category is OK to be processed
}
c.close();
// now create a different consumer with message selector ignoring "B_CATEGORY"
MessageConsumer c1 = session.createConsumer(destination, "Category <> 'B_CATEGORY'");
while ( b-is-locked ) {
Message m = c1.receive();
// process messages until b category is locked
}
c1.close();
// go to start
此示例假设您可以根据收到的消息告知何时再次处理B.如果没有,那么你可以在一定时间后恢复正常程序。该示例还只显示了一个执行线程。
进一步探索这条路径,你可以看看Spring的DefaultMessageListenerContainer
- Spring消息驱动bean。它可以完全按照我的描述进行,但采用更先进的方式。它可以通过消息选择器提供,并且它是实时的,您可以随时更改它。如果将concurrentConsumers
设置为高于1,它也会处理多个线程中的消息。
对于将消息重定向到另一个队列而无法处理的解决方案,请注意它会产生额外的流量;你确实希望最后处理你的所有消息,对吧?为什么不把它们留在原处并在适当的时候取出它们呢?你不必估计未来的重新发送延迟,这可能很难。
答案 1 :(得分:0)
您可以使用过滤器创建核心队列(或订阅),并使用管理API停止队列。或者,如果您正在使用嵌入式服务器,则可能会导致服务器队列对象暂停。
由于这是一个非常自定义的功能,您可以使用它嵌入,或在您自己的分支进行特殊调整。