我有以下Consumer
类,它侦听队列中的传入消息,然后确认并确认它们。 ack
部分工作正常,但nack
无效。由于某种原因,所有消息都被激活了。
application.properties
spring.rabbitmq.host=192.168.99.100
spring.rabbitmq.port=5677
spring.rabbitmq.username=abc
spring.rabbitmq.password=def
spring.rabbitmq.listener.acknowledge-mode=manual
Producer.java
@Component
public class Producer implements CommandLineRunner {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private Queue queue;
@Override
public void run(String... args) throws Exception {
for (int i = 0; i < 100; i++) {
this.rabbitTemplate.convertAndSend(this.queue.getName(), "Hello World !");
}
}
}
Consumer.java
@Component
public class Consumer {
private final CountDownLatch latch = new CountDownLatch(1);
int ctr = 0;
@RabbitListener(queues = "producer-consumer-nack2.q")
public void receiveQueue(String text, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws IOException, InterruptedException {
ctr++;
//nack every 10th, 20th, 30th and so on message
if (ctr % 10 == 0) {
System.out.println("Nack Message #" + ctr + ": " + text);
channel.basicNack(tag, false, true);
} else {
System.out.println("Ack Message #" + ctr + ": " + text);
channel.basicAck(tag, true);
}
latch.countDown();
}
public CountDownLatch getLatch() {
return latch;
}
}
答案 0 :(得分:2)
我相信nack的工作方式是它会拒绝然后将消息排队以便在队列中的同一点重新传递。 (参见rabbitmq文档here)
因此,当您查看处理结束时,它将被拒绝,然后再进行重新处理。
我建议调试代码,在你的nack条件(或打印)中使用断点来查看它是否命中了该代码块。然后,如果您在nack之后但在下一次处理消息之前进行调试并检查您的队列 - 我认为您会看到一条消息。