将未确认的消息(异常时)放入RabbitMQ中的其他队列

时间:2014-08-18 07:40:17

标签: java spring rabbitmq spring-amqp spring-rabbit

在处理来自RabbitMQ的消息时出现异常时,我只想取消确认并将特定消息放回到差异队列中,或者重新排队到同一队列或完全丢弃该消息(根据最后一个布尔标志@ requeue in basicNack)。

整个想法是后来我可以得到unack消息的计数并检查消息格式等,而不是一次又一次地重新排队到同一个频道,我也希望将未确认的信号发送到当前频道。

仅供参考我将channel ack模式设置为手动(即container.setAcknowledgeMode(AcknowledgeMode.MANUAL);)

这就是我现在正在做的事情。

public class My***Listener implements ChannelAwareMessageListener{

try{

    @Override
    public void onMessage(Message message,Channel channel) throws Exception {   
    String s = new String(message.getBody());
    //some logic
    //after successful ack manually
    channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }
catch(Exception e){
      //currently on exception i am unack the channel
      channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,false);
}

任何帮助都非常值得赞赏。

3 个答案:

答案 0 :(得分:4)

您可以将它们发送到死信队列。这是一个非常标准的模式。

https://www.rabbitmq.com/dlx.html

答案 1 :(得分:3)

你需要这样的东西:

@Bean
RetryOperationsInterceptor interceptor() {
    return RetryInterceptorBuilder.stateless()
            .withMaxAttempts(5)
            .setRecoverer(new RepublishMessageRecoverer(amqpTemplate(), "bar", "baz"))
            .build();
}

注意:仅适用于spring-amqp 1.3+ 另见Reference

答案 2 :(得分:1)

如果您更喜欢使用声明,请参阅this answer以获取示例。

要将邮件路由到DLX,您可以将defaultRequeuRejected设置为false(在侦听器容器上)。或者你可以抛出一个AmqpRejectAndDontRequeueException告诉容器你想要拒绝这个消息(而不是重新排队)。

容器的默认行为是重新排队被拒绝的邮件。

您可以使用带有RejectAndDontRequeueRecoverer的重试拦截器来自动抛出异常;或者,正如@ Jawo99所说,您可以使用重新发布的恢复器 - 这具有将堆栈跟踪添加为标头的额外好处。 DLX只是路由原始邮件。