RocketMQ重试机制

一、RocketMQ的生产者重试

1.可靠同步模式

原理简解:同步发送是指消息发送方发出数据后,会在收到接收方发回响应之后才发下一个数据包的通讯方式。

应用场景:这种可靠同步方式发送应用场景非常广泛,例如重要通知邮件、报名短信通知、营销短信系统等。


//可靠同步模式send方法  参数CommunicationMode.SYNC  同步
public SendResult send(Message msg, long timeout)
        throws MQClientException, RemotingException, MQBrokerException, InterruptedException{
        return sendDefaultImpl(msg, CommunicationMode.SYNC, null, timeout);
}

//默认推送broker中的方法 ,其中
 private SendResult sendDefaultImpl(Message msg, CommunicationMode communicationMode, SendCallback sendCallback, long timeout)
        throws MQClientException, RemotingException, MQBrokerException, InterruptedException
timesTotal = communicationMode != CommunicationMode.SYNC ? 1 : 1 + defaultMQProducer.getRetryTimesWhenSendFailed();

如果是CommunicationMode.SYNC的默认为defaultMQProducer.getRetryTimesWhenSendFailed()。查看源码。retryTimesWhenSendFailed = 2;默认是重试两次。

public DefaultMQProducer(String producerGroup, RPCHook rpcHook, boolean enableMsgTrace, String customizedTraceTopic)
    {
        log = ClientLogger.getLog();
        createTopicKey = "TBW102";
        defaultTopicQueueNums = 4;
        sendMsgTimeout = 3000;
        compressMsgBodyOverHowmuch = 4096;
        retryTimesWhenSendFailed = 2;
        retryTimesWhenSendAsyncFailed = 2;
        retryAnotherBrokerWhenNotStoreOK = false;
        maxMessageSize = 4194304;
        traceDispatcher = null;
        this.producerGroup = producerGroup;
        defaultMQProducerImpl = new DefaultMQProducerImpl(this, rpcHook);
        if(enableMsgTrace)
            try
            {
                AsyncTraceDispatcher dispatcher = new AsyncTraceDispatcher(producerGroup, org.apache.rocketmq.client.trace.TraceDispatcher.Type.PRODUCE, customizedTraceTopic, rpcHook);
                dispatcher.setHostProducer(defaultMQProducerImpl);
                traceDispatcher = dispatcher;
                defaultMQProducerImpl.registerSendMessageHook(new SendMessageTraceHookImpl(traceDispatcher));
            }
            catch(Throwable e)
            {
                log.error("system mqtrace hook init failed ,maybe can't send msg trace data");
            }
    }

2.可靠异步发送

原理简解:异步发送是指发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。消息队列 MQ 的异步发送,需要用户实现异步发送回调接口(SendCallback)。消息发送方在发送了一条消息后,不需要等待服务器响应即可返回,进行第二条消息发送。发送方通过回调接口接收服务器响应,并对响应结果进行处理。

应用场景:异步发送一般用于链路耗时较长,对 RT 响应时间较为敏感的业务场景,即发送端不能容忍长时间地等待 Broker 的响应。例如用户视频上传后通知启动转码服务,转码完成后通知推送转码结果等。

sendDefaultImpl(msg, CommunicationMode.ASYNC, sendCallback, timeout - costTime);

调用默认的sendDefaultImpl方法可以得出默认重试次数为1次。

3.单向发送

原理简解:单向(Oneway)发送特点为发送方只负责发送消息,不等待服务器回应且没有回调函数触发,即只发送请求不等待应答。此方式发送消息的过程耗时非常短,一般在微秒级别。

应用场景:适用于某些耗时非常短,但对可靠性要求并不高的场景,例如日志收集。

单向发送是不重试的。

二、RocketMQ的消费者重试

实现代码,通过反射机制进行消费

package com.midea.ims.hessianserver.mqlistener;
import java.lang.reflect.Method;
import java.util.List;

import org.apache.commons.lang3.SerializationUtils;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.message.MessageExt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ReflectionUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.neusoft.unieap.core.util.BeanUtil;

 
/**
 * @author : guibr
 * @date : 2020/03/09
 */
public class MqMessageListenerImpl implements MessageListenerConcurrently {
	
    private Logger logger = LoggerFactory.getLogger(MqMessageListenerImpl.class);
 
    @Override
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
    	

        logger.info(Thread.currentThread().getName()   
                + " Receive New Messages: " + msgs.size()+";msg:" + msgs);
 
 
        try{
            for(MessageExt msg : msgs){
                
                String jsonText = (String)SerializationUtils.deserialize(msg.getBody());

                JSONObject jsonObject = JSON.parseObject(jsonText);
                Object bean = BeanUtil.getBean(jsonObject.getString("beanId"));
        		Method mh = ReflectionUtils.findMethod(bean.getClass(), jsonObject.getString("beanMethod"), new Class[]{String.class}); 
        		Object[] params = new Object[]{jsonObject.getString("data")};
        		ReflectionUtils.invokeMethod(mh, bean, params); 
            }
 
        }catch (Exception e){
            logger.info("call consumeMessage | EXCEPTION :{}",e);
//            // 加入重试机制
//            if(msgs.get(0).getReconsumeTimes() == 3){
//                // 成功
//                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
//            }else{
//                // 重试
//                return ConsumeConcurrentlyStatus.RECONSUME_LATER;
//            }
            return ConsumeConcurrentlyStatus.RECONSUME_LATER;
        }
 
        // 有异常抛出来,不要全捕获了,这样保证不能消费的消息下次重推,每次重新消费间隔:10s,30s,1m,2m,3m
        // 如果没有异常会认为都成功消费
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }
}

ConsumeConcurrentlyStatus.RECONSUME_LATER。消费者默认是重试16次,16次之后就不再重试。
并且重试时间间隔逐步增加1s,5s,10s,30s,1m,2m,3m,4m,5m,6m,7m,8m,9m,10m,20m,30m,1h,2h

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值