【问题标题】:Are nonpersistent JMS messages redelivered to non-durable subscribers?非持久 JMS 消息是否重新传递给非持久订阅者?
【发布时间】:2020-03-05 01:54:02
【问题描述】:

假设我向非持久订阅者发送消息,但订阅者未能确认消息。服务器会尝试重新传递消息还是只针对持久订阅者进行重新传递?结果是否取决于消息是持久的还是非持久的?

在 Mark Richards 的《Java 消息服务》一书中,我没有找到明确的答案,但有两个看似矛盾的陈述:

acknowledge() 方法通知 JMS 提供者消息已被消费者成功接收。如果在确认过程中发生提供程序故障,此方法将向客户端抛出异常。提供程序失败会导致 JMS 服务器保留消息以进行重新传递。

这表明消息已重新传递。

如果提供者在将消息传递给具有非持久订阅的消费者时失败,则消息可能会丢失。如果持久订阅者收到一条消息,并且在向提供者返回确认之前发生了故障,则 JMS 提供者认为该消息未传递并将尝试重新传递它。

好的,那么消息可能会丢失,即没有重新发送,但这取决于什么情况?

是否有组合持久订阅者和非持久消息的用例?

【问题讨论】:

  • 我的回答是否解决了您的问题?如果是这样,请将其标记为这样,以帮助将来可能有同样问题的其他人。谢谢!

标签: java jms messaging


【解决方案1】:

您引用的每个陈述实质上都表明最终结果取决于提供者是否遇到“失败”。你的问题的答案取决于这是什么类型的失败。

在关于消息确认的第一段引文中,我相信作者是在谈论确认过程中代理内部的故障,其中代理进程保持运行但由于某种内部原因而失败。

在关于非持久订阅的第二个引用中,我相信作者在谈论代理在向消费者传递消息的过程中出现故障,其中代理进程因某种原因而终止(例如 JVM 崩溃、硬件故障) , 等等。)。在这种情况下,非持久订阅中的任何消息都将丢失,因为订阅实际上是非持久的。

作为代理开发人员,我并不真正认为这条消息“丢失”,因为这些是非持久订阅的预期语义。由于它是非持久的,因此预计不会在代理重新启动后继续存在(无论重新启动的根本原因如何)。我认为消息丢失是消息的意外删除。代理不应该丢失消息。

【讨论】:

  • 那么如果客户端没有确认消息(或者由于网络故障导致 ACK 消息丢失),Artemis 会做什么?它还会为非持久订阅者重新发送该消息吗?我会这么认为。
  • 如果代理从非持久订阅向客户端发送消息并且客户端不确认消息(无论出于何种原因),则行为取决于代理的配置。代理可以将消息放回队列中,也可以将其发送到 DLQ。无论哪种方式,消息都不会丢失。
猜你喜欢
  • 1970-01-01
  • 2018-09-22
  • 2017-11-08
  • 2012-05-30
  • 1970-01-01
  • 2017-06-27
  • 2013-12-17
  • 2015-08-24
  • 1970-01-01
相关资源
最近更新 更多