【问题标题】:Spring Rabbit : Acknowledge mode = Manual with RetryTemplate does not remove the message from queueSpring Rabbit:确认模式 = 手动使用 RetryTemplate 不会从队列中删除消息
【发布时间】:2016-09-09 22:42:30
【问题描述】:

我正在执行以下步骤:

  1. MessageListener 从队列 Q1 接收消息
  2. 验证消息
  3. 如果验证失败,调用 channel.basicReject() 并将其移至死信队列
  4. 否则,可以说,电子邮件服务器出现故障。我用 requeue true 调用 channel.basicReject() 并抛出异常。它进入重试模板并在 maxAttempts 之后被恢复(RepublishMessageRecoverer)并进入死信队列。

但它不会从 Q1 中删除消息。

public void onMessage(Message message, Channel channel) throws Exception {
        try {
            validateMessage();

            processMessage(message);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        }
        catch (DataValidationException ex){
            channel.basicReject(message.getMessageProperties().getDeliveryTag(),false);

        }
        catch(DownstreamAppException ex) {
            channel.basicReject(message.getMessageProperties().getDeliveryTag(),true);
            throw ex;
        }
    }

    void validMessage() {
        ..
        throw new DataValidationException();
    }

    void processMessage() {

        ...
        throw new DownstreamAppException();
    }

我不想重新排队验证失败的消息,但想重新排队由于某些下游应用程序失败而未处理的消息以进行重试。

几个问题: 1.如果我在DownstreamAppException的catch中没有抛出异常,消息不会去抛出retryTemplate和recoverer。是因为重新排队被拒绝的消息是一条新消息吗?

  1. 为什么消息没有从 Q1 中删除?我该如何解决?

谢谢

【问题讨论】:

    标签: rabbitmq spring-amqp spring-rabbit


    【解决方案1】:

    您有责任在使用手动确认时负责确认(无论是否重试)。如果您的代码从不应答,则消息将(最终)重新排队;但您无权访问恢复器中的通道。

    真正的问题是您为什么要使用手动确认和ChannelAwareMessageListener?您的用例很简单。使用 AUTO ackmode,容器将在成功时确认消息并在任何异常时拒绝它。

    由于recoverer重新发布了消息,这被认为是成功的,消息将被容器确认。

    要选择性地重试/重新排队,您需要一个自定义的错误处理程序,请参阅this answer for more information

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 2016-08-25
    • 2017-10-02
    • 2016-04-29
    • 2022-06-10
    • 2020-02-26
    相关资源
    最近更新 更多