在RabbitMQ中手动确认消息

在RabbitMQ中手动确认消息,rabbitmq,spring-amqp,spring-rabbit,Rabbitmq,Spring Amqp,Spring Rabbit,以前我读取队列中的所有消息,但现在我必须根据用户的选择(计数)返回特定数量的消息 我尝试相应地更改for循环,但由于自动确认,它读取所有消息。所以我试着在配置文件中将其更改为手动 在我的程序中,如何在读取消息后手动确认消息(目前我正在使用AmqpTemplate接收,并且我没有通道的参考) 任何帮助都是非常值得感谢的,请提前感谢。您不能使用receive()方法手动确认-对于具有手动确认和ChannelAwareMessageListener的事件驱动消费者,请使用SimpleMessageLi

以前我读取队列中的所有消息,但现在我必须根据用户的选择(计数)返回特定数量的消息

我尝试相应地更改for循环,但由于自动确认,它读取所有消息。所以我试着在配置文件中将其更改为手动

在我的程序中,如何在读取消息后手动确认消息(目前我正在使用AmqpTemplate接收,并且我没有通道的参考)


任何帮助都是非常值得感谢的,请提前感谢。

您不能使用
receive()
方法手动确认-对于具有手动确认和
ChannelAwareMessageListener
的事件驱动消费者,请使用
SimpleMessageListener容器。或者,使用模板的
execute()
方法,该方法允许您访问
通道
——但随后您将使用较低级别的RabbitMQ API,而不是
消息
抽象

编辑:

您需要学习使用execute的底层RabbitMQ Java API,但是类似的东西可以工作

    final int messageCount = 3;
    boolean result = template.execute(new ChannelCallback<Boolean>() {

        @Override
        public Boolean doInRabbit(final Channel channel) throws Exception {
            int n = messageCount;
            channel.basicQos(messageCount); // prefetch
            long deliveryTag = 0;
            while (n > 0) {
                GetResponse result = channel.basicGet("si.test.queue", false);
                if (result != null) {
                    System.out.println(new String(result.getBody()));
                    deliveryTag = result.getEnvelope().getDeliveryTag();
                    n--;
                }
                else {
                    Thread.sleep(1000);
                }
            }
            if (deliveryTag > 0) {
                channel.basicAck(deliveryTag, true);
            }
            return true;
        }
    });
final int messageCount=3;
布尔结果=template.execute(新ChannelCallback(){
@凌驾
公共布尔doInRabbit(最终通道)引发异常{
int n=消息计数;
channel.basicQos(messageCount);//预取
long deliveryTag=0;
而(n>0){
GetResponse result=channel.basicGet(“si.test.queue”,false);
如果(结果!=null){
System.out.println(新字符串(result.getBody());
deliveryTag=result.getEnvelope().getDeliveryTag();
n--;
}
否则{
睡眠(1000);
}
}
如果(deliveryTag>0){
channel.basicAck(deliveryTag,true);
}
返回true;
}
});

AmqpTemplate#接收
自动确认消息,除非该频道已交易。要控制确认,您可以使用
amqpmetplate#execute
并手动执行接收,或者最好的方法是使用
SimpleMessageListenerContainer
,甚至是
BlockingQueueConsumer
@NicolasLabrot我在amqpmetplate中没有找到execute方法,您指的是其他方法吗。是的,我确实在SimpleMessageListenerContainer中将setAcknowledgeMode设置为手动。对不起,我指的是
RabbitTemplate\execute
,它是
AmqpTemplate
@NicolasLabrot的一个实现,请您对此进行说明。什么是ChannelCallback,看起来我需要一个我没有的通道参考。看一下,但我认为这不是正确的方法。GaryRussell你能指出一些如何使用execute()的示例代码吗,我对这个非常陌生,我没有太多关于这个的论坛。提前感谢通常会将答案标记为已接受(单击复选标记)如果它回答了你的问题,这将有助于其他用户寻找相同的答案。@ GayyruSurl如果我们使用“接收*”方法,Spring使用“无模式”或“自动模式”吗?这意味着,它是否允许RabBMQ认为消息是自动传送的,还是在收到消息后Spring做了ACK?不要在评论中问新问题,特别是在六年前的答案上返回。确认模式仅适用于侦听器容器。模板在返回之前调用
basicAck
。如果要拒绝并重新查询消息,必须在事务中运行
receive()
方法并引发异常,以便回滚
basicAck
,并重新查询消息。
    final int messageCount = 3;
    boolean result = template.execute(new ChannelCallback<Boolean>() {

        @Override
        public Boolean doInRabbit(final Channel channel) throws Exception {
            int n = messageCount;
            channel.basicQos(messageCount); // prefetch
            long deliveryTag = 0;
            while (n > 0) {
                GetResponse result = channel.basicGet("si.test.queue", false);
                if (result != null) {
                    System.out.println(new String(result.getBody()));
                    deliveryTag = result.getEnvelope().getDeliveryTag();
                    n--;
                }
                else {
                    Thread.sleep(1000);
                }
            }
            if (deliveryTag > 0) {
                channel.basicAck(deliveryTag, true);
            }
            return true;
        }
    });