【问题标题】:How to guarantee JMS reliable delivery如何保证 JMS 可靠交付
【发布时间】:2014-12-25 17:45:20
【问题描述】:

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

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

那么可靠性是一个问题。假设当Database A 中的数据记录应该始终标记为delivered 时,当包含数据记录的消息被真正消费并持久化Database B 中的数据。然后是问题:

    1234563那么这是否意味着没有办法为这种确认机制开发一种普遍适用于所有 JMS 产品(ActiveMQ、WebSphere MQ 和 Jboss MQ)的机制?
  1. 考虑停电的情况,那么它是否会使队列中的消息消失而需要重新发送?或者不同的 JMS 产品可以拾取剩下的东西,因为消息是序列化的,所以丢失的消息只能由事务管理或异步/同步配置引起,而不是因为应用程序服务器关闭?

【问题讨论】:

    标签: java spring jakarta-ee jms


    【解决方案1】:

    1) 根据我使用队列管理器(MQ 系列、ActiveMQ 和 HornetQ)的经验,我从来不需要生产者/消费者之间的这种确认。也是我过去处理的环境,每天的流量约为 50/60 百万个对象在几个队列中。而且队列也都是持久化的。

    2) 就我而言,使用队列管理器上的持久性机制完全足以处理停电情况。我在 MQ 系列和 HornetQ 上使用了磁盘持久性。

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

    在我看来,您必须在系统架构上衡量匹配这些信息的重要性,因为这并不容易保存。

    问候。

    【讨论】:

    • 谢谢。所以我猜blackout 容差是由应用程序服务器(Websphere、WebLogic、Jboss...)提供的,那么 ActiveMQ 怎么样才能让应用程序自己可靠呢?
    • 我认为您可以查看 ActiveMQ 文档的持久性部分 (activemq.apache.org/persistence.html)。从 4.1 版开始,您可以使用磁盘或数据库设置持久性功能。我从未在这个队列管理器上使用过,但我知道这是可能的。 :)
    • 感谢您的快速回复。我必须保持问题开放一段时间以邀请更多意见,但您的想法很宝贵:)
    • 完全没问题。我很乐意提供帮助。问候。
    【解决方案2】:

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

    仅供参考,我将 Apache Camel 用于这种类型的流程,它在生产者/消费者之间具有很好的错误处理能力。

    【讨论】:

    • JTA 表示 Java 事务 API,它只是 Java 中事务管理的 JSR,与 RDBMS/MQ 供应商支持无关。我想你想说 XA(多资源分布式事务)注意 JMS 也是一个 java ee JSR,所以所有实现都是 xa 兼容的(如果不是,它们不提供 JMS 实现,而是提供简单的消息传递)
    • 此外,事务永远不会跨越妈妈边界(生产者和消费者)分布,因为它与 MOM 的消息传递异步性质相冲突。生产消息可能是事务性的,也可能是消费性的,但它们永远不会成为同一事务的一部分。
    • 是的,JTA/XA,谢谢。我认为我们对 MOM 有不同的定义。一些(比如activemq)实现了JMS API并且支持XA事务,但是一些(比如rabbitmq)没有实现JMS API并且不支持全局事务。当然,很多 DB(和 DB 驱动程序)不支持 XA。我的观点是,全局事务应该能够让生产者知道消费者成功/失败(并且 Spring tx 管理器可以提供帮助)。
    【解决方案3】:

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

    各种机制确保可靠性:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-29
      • 2016-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-07
      • 2016-03-11
      • 1970-01-01
      相关资源
      最近更新 更多