如何保证JMS可靠的交付

Dre*_*mer 6 java spring jms java-ee

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

Database A ===> Producer ===> JMS Queue ===> Consumer ===> Database B
Run Code Online (Sandbox Code Playgroud)

然后可靠性是一个问题.假设是否Database A应该始终将数据记录标记为delivered,当包含数据记录的消息被真正消耗并且保留数据时Database B.然后有问题:

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

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

Gab*_*ica 4

JMS 本质上保证消息的传递,如果消息被发布,那么它将传递给消费者(如果有),无论发生什么,MOM 旨在确保这一事实。无论如何,交付并不一定意味着已处理。

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

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

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

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

注意:如果您的数据库不支持 XA(或为了提高性能),并且事务中仅隐含 2 个资源(数据库和 JMS 队列),您可以查看记录最后一个资源事务优化