2011-12-06 150 views
3

如何确保消息确认仅删除消息,直至在jms代理中调用确认的消息。 目前我有一个系统,它从一个jms队列中消耗并部分处理它。一段时间后,一批这些消息被另一个线程持久化。我现在需要对消息进行确认。但问题是我不得不停止使用消息,否则确认之前收到的消息也会确认接收到的所有其他消息。Jms消息仅在消息得到确认之前确认

换句话说,假设我有一个队列中有10条消息。我消耗了其中的7个,然后在第5条消息上承认。这又消除了消费者从队列中接收到的所有7个消息。是否有一种方法仅确认并从队列中移除消息直到第5消息。

编辑:我试过创建两个会话,并从不同的会话消耗,但(与Apache的qpid atleast)这执行不一致。我的意思是不一致,有时候在测试过程中,一个消费者能够接收消息,而另一个消费者根本无法接收消息,无论你等待多久。这对我来说是一种解决方案,但由于不一致,无法将其作为解决方案。

+0

您还没有指定您正在使用的邮件提供程序。但据我所知,许多消息提供商不允许随机的消息确认。如果您确认收到一条消息,则直到此时收到的所有消息也会被确认并从队列中移除 – Shashi

+0

我使用apache qpid,并且我没有做随机确认,而是对特定消息做出确认。如果之前的所有消息都被清除,那么确定,但是如果接收到更多消息,它们也会被删除。 – Raks

回答

4

我知道这篇文章已经过时了,但这个答案应该会让那些稍后偶然发现的人受益。

如果您想要细致地控制您要确认哪些邮件,individual确认方法应该会对您有所帮助。使用此确认模式,您可以在会话中查看单个消息。未被确认的消息将被重新发送。

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

Oracle

更多的灵活性,消息队列可以自定义JMS 客户确认模式。在客户端确认模式下,客户端 通过调用消息对象的确认()方法明确确认消息消耗。

的 标准的行为,这种方法是导致会话承认 已经由出席会议的所有消费者自上次 调用方法消耗的所有消息。 (也就是说,会议承认当前 消息,所有以前未确认的消息,不管是谁 消耗他们。)

除了通过JMS规定的标准的行为,消息队列 ,您可以使用客户确认模式在 时间确认一条消息。

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

ActiveMQ

可以想见其它确认模式,这将是有用的也为 例如:CONSUMER_ACKNOWLEDGE其中Message.acknowledge()将 仅确认消息中接收了关于特定的MessageConsumer , 或CONSUMER_CHECKPOINT_ACKNOWLEDGE其中Message.acknowledge()将 只确认收到的消息,直到并包括消息 实例该方法被调用。

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

connection.createQueueSession(false, ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE); 

我没有用过QPID个人,但是documentation hints的事实,个人信息的ACK是可能的。

Examples 
    # acknowledge all received messages 
    session.acknowledge 

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

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

1

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

+0

问题是消费者收到的所有消息都被删除,并且它不依赖于您正在查看的消息。我想实现一些只能删除某条消息的东西,即使我之后可能会收到更多的消息。这是必需的,因为我批量处理消息,并且每当批处理完成时,我都需要确认该批次。而这批处理很耗时,所以我想继续并行接收消息 – Raks

+0

不,这是不可能的。当收到一条消息时,所有收到的消息都将被删除。您可能需要查看替代方案。 – Shashi