【RocketMQ源码分析】重试机制

本文深入探讨RocketMQ的重试机制,包括生产端和消费端的重试策略。当生产者发送消息未收到Broker确认或消费者消费消息后未正确返回状态时,RocketMQ会启动重试机制。消费端重试分为异常重试和超时重试,超过一定次数后消息将被投递到死信队列。理解这一机制对于保证消息的可靠传输至关重要。
摘要由CSDN通过智能技术生成

我们知道RocketMQ消息处理成功的标志是消费者消费一条消息后向Broker端发送ACK消息(ack,message back)并且被Broker处理。这个过程中是涉及到网络传输,有网络的地方就存在不确定性,如果由于网络等原因导致ACK丢失,则RocketMQ会触发消息消费重试机制,重新消费该条消息。RocketMQ支持了生产端和消费端两类重试机制。

生产端重试

  1. 如果由于网络抖动等原因,Producer程序向Broker发送消息时没有成功,即发送端没有收到Broker的ACK,导致最终Consumer无法消费消息,此时RocketMQ会自动进行重试。

  2. 相关API

DefaultMQProducer可以设置消息发送失败的最大重试次数,并可以结合发送的超时时间来进行重试的处理,具体API如下:

//设置消息发送失败时的最大重试次数
public void setRetryTimesWhenSendFailed(int retryTimesWhenSendFailed) {
   
   this.retryTimesWhenSendFailed = retryTimesWhenSendFailed;
}

//同步发送消息,并指定超时时间
public SendResult send(Message msg,
                      long timeout) throws MQClientException, RemotingException, MQBrokerException, InterruptedException {
   
   return this.defaultMQProducerImpl.send(msg, timeout);
}

因此,实现生产端的重试十分简单,例如下面的代码可以设置Producer如果在5s内没有发送成功,则重试5次:

//同步发送消息,如果5秒内没有发送成功,则重试5次
DefaultMQProducer producer = new DefaultMQProducer("DefaultProducer");
producer.setRetryTimesWhenSendFailed(5);
producer.send(msg,5000L);

消费端重试

  1. 消费状态:

消费者消费消息后,需要给Broker返回消费状态。以MessageListenerConcurrently监听器为例,Consumer消费完成后需要返回ConsumeConcurrentlyStatus并发消费状态。查看源码,ConsumeConcurrentlyStatus是一个枚举,共有两种状态:

public enum ConsumeConcurrentlyStatus {
   
   //消费成功
   CONSUME_SUCCESS,

   //消费失败,一段时间后重试
   RECONSUME_LATER;
}

Consumer端的重试包括两种情况

  1. 异常重试:由于Consumer端逻辑出现了异常,导致返回了RECONSUME_LATER状态,那么Broker就会在一段时间后尝试重试。
  2. 超时重试:如果Consumer端处理时间过长,或者由于某些原因线程挂起,导致迟迟没有返回消费状态,Broker就会认为Consumer消费超时,此时会发起超时重试。
    因此,如果Consumer端正常消费成功,一定要返回ConsumeConcurrentlyStatus.CONSUME_SUCCESS状态。

下面分别演示两种重试。
2. 异常重试

RocketMQ可在broker.conf文件中配置Consumer端的重试次数和重试时间间隔,如下:

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

但是在大部分情况下,如果Consumer端逻辑出现异常,重试太多次也没有很大的意义,我们可以在代码中指定最大的重试次数。如下:

public abstract class BaseConsumer implements MessageListenerConcurrently {
   

    private final static Logger logger = LoggerFactory.getLogger(BaseConsumer.class);
    private final</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值