RocketMQ错误消息重试策略之Producer的重试机制

package cn.learn.rocketmq.error;

import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;

public class SyncProducer {

    public static void main(String[] args) throws Exception {
        DefaultMQProducer producer = new DefaultMQProducer("LEARN_IM");
        producer.setNamesrvAddr("localhost:9876");

        //消息发送失败时,重试3次
        producer.setRetryTimesWhenSendFailed(3);

        producer.start();
        String msgStr = "用户A发送消息给用户B";
        Message msg = new Message("learn_im_topic", "SEND_MSG",
                msgStr.getBytes(RemotingHelper.DEFAULT_CHARSET));

        // 发送消息,并且指定超时时间
        SendResult sendResult = producer.send(msg, 1000);

        System.out.println("消息状态:" + sendResult.getSendStatus());
        System.out.println("消息id:" + sendResult.getMsgId());
        System.out.println("消息queue:" + sendResult.getMessageQueue());
        System.out.println("消息offset:" + sendResult.getQueueOffset());
        System.out.println(sendResult);

        producer.shutdown();
    }
}
public SendResult send(Message msg, long timeout) throws MQClientException, RemotingException, MQBrokerException, InterruptedException {
	return this.defaultMQProducerImpl.send(msg, timeout);
}
private SendResult sendDefaultImpl(Message msg, CommunicationMode communicationMode, SendCallback sendCallback, long timeout) throws MQClientException, RemotingException, MQBrokerException, InterruptedException {
	this.makeSureStateOK();
	Validators.checkMessage(msg, this.defaultMQProducer);
	long invokeID = this.random.nextLong();
	long beginTimestampFirst = System.currentTimeMillis();
	long beginTimestampPrev = beginTimestampFirst;
	TopicPublishInfo topicPublishInfo = this.tryToFindTopicPublishInfo(msg.getTopic());
	if (topicPublishInfo != null && topicPublishInfo.ok()) {
		boolean callTimeout = false;
		MessageQueue mq = null;
		Exception exception = null;
		SendResult sendResult = null;
		int timesTotal = communicationMode == CommunicationMode.SYNC ? 1 + this.defaultMQProducer.getRetryTimesWhenSendFailed() : 1;
		int times = 0;
		String[] brokersSent = new String[timesTotal];

		while(true) {
			label122: {
				String info;
				if (times < timesTotal) {
					info = null == mq ? null : mq.getBrokerName();
					MessageQueue mqSelected = this.selectOneMessageQueue(topicPublishInfo, info);
					if (mqSelected != null) {
						mq = mqSelected;
						brokersSent[times] = mqSelected.getBrokerName();

						long endTimestamp;
						try {
							beginTimestampPrev = System.currentTimeMillis();
							long costTime = beginTimestampPrev - beginTimestampFirst;
							if (timeout >= costTime) {
								sendResult = this.sendKernelImpl(msg, mq, communicationMode, sendCallback, topicPublishInfo, timeout - costTime);
								endTimestamp = System.currentTimeMillis();
								this.updateFaultItem(mq.getBrokerName(), endTimestamp - beginTimestampPrev, false);
								switch(communicationMode) {
								case ASYNC:
									return null;
								case ONEWAY:
									return null;
								case SYNC:
									if (sendResult.getSendStatus() == SendStatus.SEND_OK || !this.defaultMQProducer.isRetryAnotherBrokerWhenNotStoreOK()) {
										return sendResult;
									}
								default:
									break label122;
								}
							}

							callTimeout = true;
						} catch (RemotingException var26) {
							endTimestamp = System.currentTimeMillis();
							this.updateFaultItem(mqSelected.getBrokerName(), endTimestamp - beginTimestampPrev, true);
							this.log.warn(String.format("sendKernelImpl exception, resend at once, InvokeID: %s, RT: %sms, Broker: %s", invokeID, endTimestamp - beginTimestampPrev, mqSelected), var26);
							this.log.warn(msg.toString());
							exception = var26;
							break label122;
						} catch (MQClientException var27) {
							endTimestamp = System.currentTimeMillis();
							this.updateFaultItem(mqSelected.getBrokerName(), endTimestamp - beginTimestampPrev, true);
							this.log.warn(String.format("sendKernelImpl exception, resend at once, InvokeID: %s, RT: %sms, Broker: %s", invokeID, endTimestamp - beginTimestampPrev, mqSelected), var27);
							this.log.warn(msg.toString());
							exception = var27;
							break label122;
						} catch (MQBrokerException var28) {
							endTimestamp = System.currentTimeMillis();
							this.updateFaultItem(mqSelected.getBrokerName(), endTimestamp - beginTimestampPrev, true);
							this.log.warn(String.format("sendKernelImpl exception, resend at once, InvokeID: %s, RT: %sms, Broker: %s", invokeID, endTimestamp - beginTimestampPrev, mqSelected), var28);
							this.log.warn(msg.toString());
							exception = var28;
							switch(var28.getResponseCode()) {
							case 1:
							case 14:
							case 16:
							case 17:
							case 204:
							case 205:
								break label122;
							default:
								if (sendResult != null) {
									return sendResult;
								}

								throw var28;
							}
						} catch (InterruptedException var29) {
							endTimestamp = System.currentTimeMillis();
							this.updateFaultItem(mqSelected.getBrokerName(), endTimestamp - beginTimestampPrev, false);
							this.log.warn(String.format("sendKernelImpl exception, throw exception, InvokeID: %s, RT: %sms, Broker: %s", invokeID, endTimestamp - beginTimestampPrev, mqSelected), var29);
							this.log.warn(msg.toString());
							this.log.warn("sendKernelImpl exception", var29);
							this.log.warn(msg.toString());
							throw var29;
						}
					}
				}

				if (sendResult != null) {
					return sendResult;
				}

				info = String.format("Send [%d] times, still failed, cost [%d]ms, Topic: %s, BrokersSent: %s", times, System.currentTimeMillis() - beginTimestampFirst, msg.getTopic(), Arrays.toString(brokersSent));
				info = info + FAQUrl.suggestTodo("http://rocketmq.apache.org/docs/faq/");
				MQClientException mqClientException = new MQClientException(info, (Throwable)exception);
				if (callTimeout) {
					throw new RemotingTooMuchRequestException("sendDefaultImpl call timeout");
				}

				if (exception instanceof MQBrokerException) {
					mqClientException.setResponseCode(((MQBrokerException)exception).getResponseCode());
				} else if (exception instanceof RemotingConnectException) {
					mqClientException.setResponseCode(10001);
				} else if (exception instanceof RemotingTimeoutException) {
					mqClientException.setResponseCode(10002);
				} else if (exception instanceof MQClientException) {
					mqClientException.setResponseCode(10003);
				}

				throw mqClientException;
			}

			++times;
		}
	} else {
		List<String> nsList = this.getmQClientFactory().getMQClientAPIImpl().getNameServerAddressList();
		if (null != nsList && !nsList.isEmpty()) {
			throw (new MQClientException("No route info of this topic, " + msg.getTopic() + FAQUrl.suggestTodo("http://rocketmq.apache.org/docs/faq/"), (Throwable)null)).setResponseCode(10005);
		} else {
			throw (new MQClientException("No name server address, please set it." + FAQUrl.suggestTodo("http://rocketmq.apache.org/docs/faq/"), (Throwable)null)).setResponseCode(10004);
		}
	}
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值