RocketMq broker 重试和死信队列

系列

  • RocketMq broker 配置文件
  • RocketMq broker 启动流程
  • RocketMq broker CommitLog介绍
  • RocketMq broker consumeQueue介绍
  • RocketMq broker 重试和死信队列
  • RocketMq broker 延迟消息
  • RocketMq IndexService介绍
  • RocketMq 读写分离机制
  • RocketMq Client管理
  • RocketMq Broker线程模型及快速失败机制
  • RocketMq broker过期文件删除

开篇

  • 这个系列的主要目的是介绍RocketMq broker的原理和用法,在这个系列当中会介绍 broker 配置文件、broker 启动流程、broker延迟消息、broker消息存储、broker的重试和死信队列。

  • 这篇文章主要介绍broker 重试和死信队列,本质上所有的数据都是存在commitLog文件的,只是consumeQueue根据topic的不同进行了区分,所以数据存储过程可以参考 RocketMq broker CommitLog介绍 和 RocketMq broker consumeQueue介绍。

  • 重试队列和死信队列本质上进入到了对应topic下的consumeQueue而已。


重试和死信队列topic替换

public class SendMessageProcessor extends AbstractSendMessageProcessor implements NettyRequestProcessor {

    public static final String RETRY_GROUP_TOPIC_PREFIX = "%RETRY%";
    public static final String DLQ_GROUP_TOPIC_PREFIX = "%DLQ%";

    private boolean handleRetryAndDLQ(SendMessageRequestHeader requestHeader, RemotingCommand response,
                                      RemotingCommand request,
                                      MessageExt msg, TopicConfig topicConfig) {
        // 获取topic进行判断逻辑
        String newTopic = requestHeader.getTopic();
        // 重试队列是以%RETRY%+consumerGroup作为维度的
        if (null != newTopic && newTopic.startsWith(MixAll.RETRY_GROUP_TOPIC_PREFIX)) {
            String groupName = newTopic.substring(MixAll.RETRY_GROUP_TOPIC_PREFIX.length());
            SubscriptionGroupConfig subscriptionGroupConfig =
                this.brokerController.getSubscriptionGroupManager().findSubscriptionGroupConfig(groupName);
            if (null == subscriptionGroupConfig) {
                response.setCode(ResponseCode.SUBSCRIPTION_GROUP_NOT_EXIST);
                response.setRemark(
                    "subscription group not exist, " + groupName + " " + FAQUrl.suggestTodo(FAQUrl.SUBSCRIPTION_GROUP_NOT_EXIST));
                return false;
            }
            // 获取最大重试次数
            int maxReconsumeTimes = subscriptionGroupConfig.getRetryMaxTimes();
            if (request.getVersion() >= MQVersion.Version.V3_4_9.ordinal()) {
                maxReconsumeTimes = requestHeader.getMaxReconsumeTimes();
            }
            int reconsumeTimes = requestHeader.getReconsumeTimes() == null ? 0 : requestHeader.getReconsumeTimes();
            // 超过最大重试次数之后发送到死信队列
            if (reconsumeTimes >= maxReconsumeTimes) {
                // 死信队列是以% DLQ%+consumerGroup作为维度的
                newTopic = MixAll.getDLQTopic(groupName);
                int queueIdInt = Math.abs(this.random.nextInt() % 99999999) % DLQ_NUMS_PER_GROUP;
                topicConfig = this.brokerController.getTopicConfigManager().createTopicInSendMessageBackMethod(newTopic,
                    DLQ_NUMS_PER_GROUP,
                    PermName.PERM_WRITE, 0
                );
                msg.setTopic(newTopic);
                msg.setQueueId(queueIdInt);
                if (null == topicConfig) {
                    response.setCode(ResponseCode.SYSTEM_ERROR);
                    response.setRemark("topic[" + newTopic + "] not exist");
                    return false;
                }
            }
        }
        int sysFlag = requestHeader.getSysFlag();
        if (TopicFilterType.MULTI_TAG == topicConfig.getTopicFilterType()) {
            sysFlag |= MessageSysFlag.MULTI_TAGS_FLAG;
        }
        msg.setSysFlag(sysFlag);
        return true;
    }
}
  • 重试队列是以%RETRY%+consumerGroup作为维度的生成consumeQueue。
  • 死信队列是以%DLQ%+consumerGroup作为维度的生成consumeQueue。
  • 进入死信队列的条件是重试次数超过了最大重试次数。
  • 死信队列的topic是在消息发送过程中判断对应的topic是否存在,不存在就动态进行创建。

你可能感兴趣的:(RocketMq broker 重试和死信队列)