如何保证JMS可靠的交付

时间:2014-10-29 20:37:59

标签: java spring java-ee jms

我认为使用JMS的很多(在我的情况下是Spring)应用程序可能会遵循这个工作流程:

Database A ===> Producer ===> JMS Queue ===> Consumer ===> Database B

然后可靠性是一个问题。让我们说一下Database A中的数据记录是否应该始终标记为delivered,当邮件中包含数据记录的时候是真实消耗的,并将数据保存在Database B中。然后有问题:

  1. 据我所知,目前JMS协议没有定义任何从consumerproducer发送确认的功能,但仅限于MOM,因此实际consumer-to-producer确认方法因JMS提供程序而异。那么这是否意味着没有办法开发一种可以用于通常所有JMS产品(ActiveMQ,WebSphere MQ和Jboss MQ)的确认机制?

  2. 考虑停电的情况,然后它是否会使队列中的消息消失,所以需要重新发送?或者不同的JMS产品可以获取剩余的内容,因为消息是序列化的,因此丢失的消息只能由事务管理或异步/同步配置引起,而不是因为应用程序服务器已关闭?

3 个答案:

答案 0 :(得分:4)

JMS保证了消息的本质传递,如果消息被发布,那么无论发生什么,它都会传递给消费者,无论发生什么,MOM都是为了确保这一事实而设计的。无论如何,交付没有必要意味着处理。

通过各种机制确保可靠性:

  • 第一个是队列中消息的持久性(队列和消息必须标记为持久性,这是默认值),以确保在系统中断时不会丢失消息。
  • 然后您有确认和重试策略,消息将保留在队列中,直到消费者确认它,并且在交易会话的情况下,将重新传递,直到消费者有效地处理消息或达到最大重试。然后可以将失败的消息重定向到死信队列进行分析。

为了确保两个数据源之间的一致性,您必须至少在生产者端使用XA事务(事务数据库A和JMS队列中至少隐含了2个资源),以保证消息不会出现如果数据库A中的提交失败,则发布到队列,如果队列的发布失败,则不会更新数据库。消息消耗也应该进行处理以确保在回滚的情况下重新传递。

事务边界永远不会同时包含使用者和生产者,因为它与消息传递系统的异步性质相冲突,在消费者处理消息之前,您无法锁定生产者端的资源,因为您无法保证何时会发生。

注意:如果您的数据库不支持XA(或提高性能),并且您在事务(数据库和JMS队列)中只隐含了2个资源,那么您可以查看Logging Last Resource Transaction Optimization < / p>

答案 1 :(得分:2)

1)根据我对队列管理器(MQ Series,ActiveMQ和HornetQ)的经验,我从不需要生产者/消费者之间的这种认可。此外,我曾经处理过的环境,流量在几个队列中每天约有50/60万个对象。队列也都坚持了下来。

2)就我而言,在队列管理器上使用持久性机制完全足以处理中断场景。我在MQ Series和HornetQ上使用了磁盘持久性。

但是,有时为了确定消息量,我们开发了一些机制来比较数据库A和数据库B,以确保消息也被消费。我不知道JMS架构是否应该提供这种机制,因为这样的任务可能会降低性能。

在我的观点中,你必须衡量一下你的系统架构,衡量这些信息的重要性,因为它并不容易保存。

问候。

答案 2 :(得分:1)

如果我理解你的问题,这似乎就是JTA / XA事务的情况(只要你的DB / JMS供应商支持它们)。 Spring TX经理可以帮助使tx管理(更多)供应商不可知。

仅供参考,我使用Apache Camel来实现这种类型的流程,它在生产者/消费者中具有相当好的错误处理能力。