RocketMQ消费消息失败的处理办法

一般的,我们在RocketMQ处理消息的时候,可能会在消费者中使用类似下面的代码

consumer.registerMessageListener(new MessageListenerConcurrently() {
  @Override
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
        ConsumeConcurrentlyContext context) {
        System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs);
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }
});

如果消息被成功消费的话,会返回ConsumeConcurrentlyStatus.CONSUME_SUCCESS状态,但是如果消息消费失败的话,又会怎么处理呢?

其实我们只要找到ConsumeConcurrentlyStatus这个枚举就能知道RocketMQ是如何处理了,代码如下:

public enum ConsumeConcurrentlyStatus {
    /**
     * Success consumption
     */
    CONSUME_SUCCESS,
    /**
     * Failure consumption,later try to consume
     */
    RECONSUME_LATER;
}

很明显,如果无法返回CONSUME_SUCCESS状态,那么就返回RECONSUME_LATER,过一会再尝试消费即可。那么第二个问题来了,既然这条消息消费失败了,总不能一直卡着后面的消息也等着吧,那么消费失败的消息肯定需要放到另一个Topic中,让它一个人等着被再次消费

所以这时会有一个重试队列,用于暂时保存因为各种异常而导致Consumer端无法消费的消息,重试队列的名称是在原队列的名称前加上%RETRY%(这个Topic的重试队列是针对消费组,而不是针对每个Topic设置的)
RocketMQ对于重试消息的处理是先保存至Topic名称为“SCHEDULE_TOPIC_XXXX”的延迟队列中,后台定时任务按照对应的时间进行Delay后重新保存至“%RETRY%+consumerGroup”的重试队列中

在RocketMQ的console控制台上可以看到重试队列的信息
RocketMQ消费消息失败的处理办法_第1张图片
现在我们已经知道消费失败的消息会进入重试队列,那么多久重试一次呢?能进行多少次的重试呢?
考虑到异常恢复起来需要一些时间,会为重试队列设置多个重试级别,每个重试级别都有与之对应的重新投递延时间,重试次数越多投递延时就越大。有一个参数messageDelayLevel,这个参数是在服务器端的Broker上配置的,默认是

messageDelayLevel=1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h

默认是最多可以重试16次

如果重试了16次之后,这条消息还是没有被成功消费,那么就认为这条消息是抢救不过来了,此时,消息队列不会立刻将消息丢弃,于是它被放入了死信队列中,上面重试队列的图中你也可以看到死信队列,死信队列的名称是在原队列名称前加%DLQ%。如果你还是不死心的话,觉得这条消息还能抢救一下,可以开启一个后台线程不断扫描死信队列然后继续重试,也可以通过使用console控制台对死信队列中的消息进行重发来使得消费者实例再次进行消费

整个消费失败流程如图所示
RocketMQ消费消息失败的处理办法_第2张图片

你可能感兴趣的:(RocketMQ)