2011-11-27 121 views
4

我正在尝试编写使用JMS发布订阅模型的应用程序。不过,我遇到了挫折,我希望能够让发布商从主题中删除消息。用例是我拥有持久订阅者,活跃订阅者会得到这些消息(因为它或多或少是即时的),但是如果存在不活动的消息并且发布者决定消息是错误的,我希望让他能够删除消息以便用户一旦活动就不会再收到它。 问题是,我不知道如何做到这一点。 对于一家供应商我决定使用glassfish的实现,但如果其他替代方案提供此功能,我可以切换。如何从主题中删除邮件

谢谢。

回答

6

JMS是异步消息传递的一种形式,因此发布者和订阅者通过设计分离。这意味着没有机制去做你正在问的东西。对于在发布时处于活动状态的订阅者,他们将消费该消息而没有及时收到删除消息的机会来处理它。如果用户不在线,那么他们会认为异步消息是原子的。如果您继续设计其他受访者的答案(创建删除消息并要求重新连接消费者以读取整个队列以查找删除消息),那么您将创建一种情况,其中系统的行为会根据订阅者是否有所不同在发布特定消息/删除组合时已上线或未上线。在发布者发出删除消息之前,用户还完成读取保留消息的竞争条件。这意味着您必须向订阅者提供重要的逻辑来协调这些条件,甚至更好地协调竞争条件。

这样做的接受方法是所谓的“补偿交易”。在生产者和消费者不共享单个工作单元或共享共同状态的任何系统中(例如使用相同的DB来存储状态),则退出或更正以前的事务需要第二次事务处理,即第一次事务处理。消费者当然必须能够正确地应用补偿交易。当使用这种模式时,结果是所有订户都表现出相同的行为,无论消费者重新启动后消息是实时还是批量消费。

请注意,补偿交易与“删除消息”不同。另一个答复者答案中提出的删除消息是一种影响消息流本身的命令和控制形式。另一方面,补偿事务通过事务更新系统状态来影响系统的状态。

作为一般规则,你从来没有想通过操纵带有命令和控制功能的消息流来管理系统的状态。这是脆弱的,容易受到攻击,很难审计或调试。相反,请设计系统以传递受其服务质量约束的每封邮件并处理所有邮件。完全在应用程序中处理状态更改(包括反转之前的操作)。

作为一个例子,在银行业务中,交易触发辅助效果,例如透支费用,通常的做法是在白天“备忘”交易,然后在银行关闭后对其进行分批处理和批量应用。这使得在之前出现的错误可能会导致透支费用。最近,这些交易是实时应用的,但触发器被扣留,直到当天的账单结束,并且达到相同的结果。

+0

+1,阅读您的答案总是很高兴。 – MaDa

+0

谢谢,为客气话! –

-1

您必须让制作人发送delete消息,消费者需要在开始处理消息之前阅读所有消息。

+0

谢谢,这意味着我必须照顾这部分的完整实施,但这也意味着订户将看到已删除的消息,但基本上忽略它。有没有办法阻止消息到达他? – LuBa

+0

你可以自己有过期的消息。 –

1

JMS API不允许从任何目标(队列或主题)中删除消息。尽管我相信特定的JMX提供者提供了他们自己的专有工具来管理他们的状态,例如使用JMX。尽量检查出你的JMS提供者,但要小心:即使你找到解决方案,它也不能在不同的JMS提供者之间移植。

“删除”消息的一种合法方式是使用其生存时间: publish(Topic topic, Message message, int deliveryMode, int priority, long timeToLive)。对你来说可能是够好的了。

如果它不适用于您的应用程序,请在应用程序级别解决问题。例如,将唯一ID附加到每条消息,并发布具有更高优先级的特殊“删除”消息,这将是一种删除具有相同ID的“真实”消息的命令。

相关问题