简体   繁体   English

如何从 RabbitMQ 死信队列中一一消费消息

[英]How to consume message from RabbitMQ dead letter queue one by one

The requirement is like to process the messages from dead letter queue by exposed a REST service API(Spring Boot).要求就像通过公开一个 REST 服务 API(Spring Boot)来处理来自死信队列的消息。 So that once REST service is called, one message will be consumed from the DL queue and will publish in the main queue again for processing.这样一旦调用了 REST 服务,就会从 DL 队列中消费一条消息,并再次发布到主队列中进行处理。 @RabbitListener(queues = " QUEUE_NAME ") consumes the message immediately which is not required as per the scenario. @RabbitListener(queues = " QUEUE_NAME ")立即使用消息,根据场景,这不是必需的。 The message only has to be consumed by the REST service API.该消息只能由 REST 服务 API 使用。 Any suggestion or solution?有什么建议或解决方案吗?

I do not think RabbitListener will help here.我不认为RabbitListener在这里会有所帮助。

However you could implement this behaviour manually.但是,您可以手动实现此行为。

Spring Boot automatically creates RabbitMq connection factory so you could use it. Spring Boot 会自动创建RabbitMq连接工厂,以便您使用。 When http call is made just read single message from the queue manually, you could use basic.get to synchronously get just one message:当 http 调用只是手动从队列中读取一条消息时,您可以使用basic.get同步获取一条消息:

@Autowire 
private ConnectionFactory factory 

void readSingleMessage() {
   Connection connection = null;
   Channel channel = null;
   try {
      connection = factory.newConnection();
      channel = connection.createChannel();

      channel.queueDeclare(QUEUE_NAME, true, false, false, null);

      GetResponse response = channel.basicGet(QUEUE_NAME, true);
      if (response != null) {
         //Do something with the message
      }
   } finally {
     //Check if not null
     channel.close();
     connection.close();
   }

}

If you are using Spring;如果您使用的是 Spring; you can avoid all the boilerplate in the other answer using RabbitTemplate.receive(...) .您可以使用RabbitTemplate.receive(...)避免其他答案中的所有样板。

EDIT编辑

To manually ack/reject the message, use the execute method instead.要手动确认/拒绝消息,请改用execute方法。

template.execute(channel -> {
    GetResponse got = channel.basicGet("foo", false);

    // ...

    channel.basicAck(got.getEnvelope().getDeliveryTag(), false);

    return null;
});

It's a bit lower level, but again, most of the boilerplate is taken care of for you.它的级别有点低,但同样,大部分样板文件都会为您处理好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM