4

如何确保消息确认仅删除消息,直到在 jms 代理中调用确认的消息。目前我有一个系统,它从 jms 队列中消耗并部分处理它。稍后,一批这些消息被不同的线程持久化。我现在需要确认消息。但问题是我必须停止使用这些消息,否则确认先前收到的消息也将确认收到的所有其他后续消息。

换句话说,假设我在队列中有 10 条消息。我消耗了其中的 7 个,然后在第 5 条消息上确认。这反过来会从队列中删除消费者收到的所有 7 条消息。有没有办法只从队列中确认和删除消息,直到第 5 条消息。

编辑:我尝试创建两个会话并从不同的会话中使用,但是(至少使用 apache qpid)这执行不一致。我的意思是不一致,有时在测试过程中,一个消费者能够接收消息,而另一个消费者根本没有收到消息,无论您等待多长时间。这对我来说是一个解决方案,但由于不一致,不能将其用作解决方案。

4

2 回答 2

5

我知道这篇文章很旧,但是这个答案应该对以后偶然发现它的人有所帮助。

如果您想对要确认的消息进行细粒度控制,则individual确认方法应该可以帮助您。使用此确认模式,您可以确认会话中的单个消息。尚未确认的消息将被重新传递。

这不是规范的一部分,但大多数队列提供程序在规范之外支持它。

甲骨文

为了获得更大的灵活性,Message Queue 允许您自定义 JMS 客户端确认模式。在客户端确认模式下,客户端通过调用消息对象的确认()方法显式确认消息消费。

此方法的标准行为是使会话确认自上次调用该方法以来会话中任何消费者已消费的所有消息。(也就是说,会话确认当前消息和所有以前未确认的消息,而不管是谁消费了它们。)

除了 JMS 指定的标准行为之外,Message Queue 还允许您使用客户端确认模式一次确认一条消息。

public interface com.sun.messaging.jms.Message {
          void acknowledgeThisMessage() throws JMSException;
          void acknowledgeUpThroughThisMessage() throws JMSException;
}

活动MQ

可以想象其他也有用的确认模式,例如: CONSUMER_ACKNOWLEDGE,其中 Message.acknowledge() 将仅确认在特定 MessageConsumer 上收到的消息,或 CONSUMER_CHECKPOINT_ACKNOWLEDGE,其中 Message.acknowledge() 将仅确认收到的消息,包括调用该方法的 Message 实例。

但是如果不考虑所有这些不同的可能性,是否可以考虑只添加 INDIVIDUAL_ACKNOWLEDGE 模式?仅这一点就可以让多线程应用程序实现他们需要的任何行为。

connection.createQueueSession(false, ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE);

我个人没有使用过 QPID,但是文档暗示了单个消息确认是可能的这一事实。

Examples
  # acknowledge all received messages
  session.acknowledge

  # acknowledge a single message
  session.acknowledge :message => message

在处理批处理时,您可以确认接收和处理的每条消息。如果遇到异常,请不要确认消息。

于 2014-02-21T12:21:34.123 回答
1

确认消息将使队列管理器删除该消息以及在该消息之前收到的所有其他消息。它不应该删除应用程序尚未收到的消息。您可能需要检查您的应用程序如何确认消息。

于 2011-12-08T06:39:55.963 回答