【问题标题】:Keeping messages in queue in case of receiver crash在接收器崩溃的情况下将消息保留在队列中
【发布时间】:2011-02-07 02:07:52
【问题描述】:

我们有一个用于异步接收消息的 Spring JMS 消息侦听器容器。使用 DefaultMessageListenerContainer 并处于 sessionTransacted 模式。我了解处于 sessionTransacted 模式意味着如果出现异常,消息将被放回队列中。但是,即使接收器(选择消息的)崩溃或只是运行它的机器断电,我如何确保消息不会从队列中删除?

一开始我以为 CLIENT_ACKNOWLEDGE 确认模式应该可以救我,但apparently 并非如此,Spring 无论如何都会调用 .acknowledge()。

所以这是我的问题,我如何保证交货?使用自定义 MessageListenerContainer?使用事务管理器?

【问题讨论】:

    标签: java spring jms


    【解决方案1】:

    具有 Client_Acknowledge 模式的 Spring 消息侦听器将在客户端调用 message.acknowledge() 时确认消息。

    但是,如果在成功执行消息后,消费者没有找到来自客户端的任何确认,则 spring 假定执行成功并确认消息。

    如果在任何时候,消费者在处理消息时遇到异常,spring 监听器需要知道发生了一些异常,以便将消息重新传递到队列中,以便另一个消费者线程接收它。如果您发现异常,spring 会假定一切都已处理并且执行顺利,因此会确认该消息。

    Spring 消息监听器只允许从 on​​Message 监听器抛出 JMS 异常。捕获您的自定义异常并从侦听器抛出 JMS 异常(在记录错误以供将来参考之后)将允许您重新传递消息。

    【讨论】:

      【解决方案2】:

      或者您可以将 Session.AUTO_ACKNOWLEDGE 与非事务会话一起使用,请参阅下面来自 article 的引用

      会自动发送一条消息 成功时确认 从 receive() 方法返回。如果 接收者使用 MessageListener 界面,消息是 时自动确认 从成功返回 onMessage() 方法。如果失败 在执行 receive() 时发生 方法或 onMessage() 方法, 消息会自动重新发送。 JMS 提供者精心管理 消息重新传递和保证 一次性交付语义。

      【讨论】:

      • -1 因为从本文档得出的结论不正确。是的,如果 receive() 或 onMessage() 调用失败,则会重新发送,但这并不意味着接收者有机会对消息进行处理。如果此时接收器崩溃,则消息将不可挽回地丢失,这是 OP 试图避免的。但是,如果接收方崩溃,使用事务会话和显式提交调用(如其他响应中所述)确实可以防止此类消息丢失。
      • 所以简而言之,这篇文章有误导性吗?崩溃的意义是什么?如果 onMessage 方法由于崩溃没有返回,消息会不会被重新传递?
      • 我并不是说这篇文章具有误导性,只是它不适用于原始问题。文章引用中讨论的所有失败都发生在消息返回到应用程序之前。 OP 希望延迟消息确认,直到消息返回并且应用程序处理它之后,因为 CLIENT_ACKNOWLEDGE 应该提供。设置 Session.AUTO_ACKNOWLEDGE 实际上会强制执行 OP 试图阻止的行为。
      【解决方案3】:

      使用事务处理会话并通过调用Session 类的commit() 方法指示消息处理成功。

      查看19.4.5. Processing messages within transactions 部分的配置。 (您可以使用DefaultMessageListenerContainer)。根据您对消息的处理方式,您可能需要 JTA 事务管理器。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-02-03
        • 2019-07-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-19
        • 2021-02-16
        • 2016-03-19
        相关资源
        最近更新 更多