文档章节

聊聊rocketmq broker的CONSUMER_SEND_MSG_BACK

go4it
 go4it
发布于 11/14 23:33
字数 658
阅读 13
收藏 0

本文主要研究一下rocketmq broker的CONSUMER_SEND_MSG_BACK

CONSUMER_SEND_MSG_BACK

rocketmq/common/src/main/java/org/apache/rocketmq/common/protocol/RequestCode.java

public class RequestCode {
	//......

	public static final int CONSUMER_SEND_MSG_BACK = 36;

	//......
  • RequestCode定义了CONSUMER_SEND_MSG_BACK常量,值为36

processRequest

rocketmq/broker/src/main/java/org/apache/rocketmq/broker/processor/SendMessageProcessor.java

public class SendMessageProcessor extends AbstractSendMessageProcessor implements NettyRequestProcessor {

    private List<ConsumeMessageHook> consumeMessageHookList;

    public SendMessageProcessor(final BrokerController brokerController) {
        super(brokerController);
    }

    @Override
    public RemotingCommand processRequest(ChannelHandlerContext ctx,
                                          RemotingCommand request) throws RemotingCommandException {
        SendMessageContext mqtraceContext;
        switch (request.getCode()) {
            case RequestCode.CONSUMER_SEND_MSG_BACK:
                return this.consumerSendMsgBack(ctx, request);
            default:
                SendMessageRequestHeader requestHeader = parseRequestHeader(request);
                if (requestHeader == null) {
                    return null;
                }

                mqtraceContext = buildMsgContext(ctx, requestHeader);
                this.executeSendMessageHookBefore(ctx, request, mqtraceContext);

                RemotingCommand response;
                if (requestHeader.isBatch()) {
                    response = this.sendBatchMessage(ctx, request, mqtraceContext, requestHeader);
                } else {
                    response = this.sendMessage(ctx, request, mqtraceContext, requestHeader);
                }

                this.executeSendMessageHookAfter(response, mqtraceContext);
                return response;
        }
    }

    //......
}
  • SendMessageProcessor对于request.getCode()为RequestCode.CONSUMER_SEND_MSG_BACK会执行consumerSendMsgBack方法

consumerSendMsgBack

public class SendMessageProcessor extends AbstractSendMessageProcessor implements NettyRequestProcessor {

    private List<ConsumeMessageHook> consumeMessageHookList;

    public SendMessageProcessor(final BrokerController brokerController) {
        super(brokerController);
    }

    //......

    private RemotingCommand consumerSendMsgBack(final ChannelHandlerContext ctx, final RemotingCommand request)
        throws RemotingCommandException {
        final RemotingCommand response = RemotingCommand.createResponseCommand(null);
        final ConsumerSendMsgBackRequestHeader requestHeader =
            (ConsumerSendMsgBackRequestHeader)request.decodeCommandCustomHeader(ConsumerSendMsgBackRequestHeader.class);

        String namespace = NamespaceUtil.getNamespaceFromResource(requestHeader.getGroup());
        if (this.hasConsumeMessageHook() && !UtilAll.isBlank(requestHeader.getOriginMsgId())) {

            ConsumeMessageContext context = new ConsumeMessageContext();
            context.setNamespace(namespace);
            context.setConsumerGroup(requestHeader.getGroup());
            context.setTopic(requestHeader.getOriginTopic());
            context.setCommercialRcvStats(BrokerStatsManager.StatsType.SEND_BACK);
            context.setCommercialRcvTimes(1);
            context.setCommercialOwner(request.getExtFields().get(BrokerStatsManager.COMMERCIAL_OWNER));

            this.executeConsumeMessageHookAfter(context);
        }

        SubscriptionGroupConfig subscriptionGroupConfig =
            this.brokerController.getSubscriptionGroupManager().findSubscriptionGroupConfig(requestHeader.getGroup());
        if (null == subscriptionGroupConfig) {
            response.setCode(ResponseCode.SUBSCRIPTION_GROUP_NOT_EXIST);
            response.setRemark("subscription group not exist, " + requestHeader.getGroup() + " "
                + FAQUrl.suggestTodo(FAQUrl.SUBSCRIPTION_GROUP_NOT_EXIST));
            return response;
        }

        if (!PermName.isWriteable(this.brokerController.getBrokerConfig().getBrokerPermission())) {
            response.setCode(ResponseCode.NO_PERMISSION);
            response.setRemark("the broker[" + this.brokerController.getBrokerConfig().getBrokerIP1() + "] sending message is forbidden");
            return response;
        }

        if (subscriptionGroupConfig.getRetryQueueNums() <= 0) {
            response.setCode(ResponseCode.SUCCESS);
            response.setRemark(null);
            return response;
        }

        String newTopic = MixAll.getRetryTopic(requestHeader.getGroup());
        int queueIdInt = Math.abs(this.random.nextInt() % 99999999) % subscriptionGroupConfig.getRetryQueueNums();

        int topicSysFlag = 0;
        if (requestHeader.isUnitMode()) {
            topicSysFlag = TopicSysFlag.buildSysFlag(false, true);
        }

        TopicConfig topicConfig = this.brokerController.getTopicConfigManager().createTopicInSendMessageBackMethod(
            newTopic,
            subscriptionGroupConfig.getRetryQueueNums(),
            PermName.PERM_WRITE | PermName.PERM_READ, topicSysFlag);
        if (null == topicConfig) {
            response.setCode(ResponseCode.SYSTEM_ERROR);
            response.setRemark("topic[" + newTopic + "] not exist");
            return response;
        }

        if (!PermName.isWriteable(topicConfig.getPerm())) {
            response.setCode(ResponseCode.NO_PERMISSION);
            response.setRemark(String.format("the topic[%s] sending message is forbidden", newTopic));
            return response;
        }

        MessageExt msgExt = this.brokerController.getMessageStore().lookMessageByOffset(requestHeader.getOffset());
        if (null == msgExt) {
            response.setCode(ResponseCode.SYSTEM_ERROR);
            response.setRemark("look message by offset failed, " + requestHeader.getOffset());
            return response;
        }

        final String retryTopic = msgExt.getProperty(MessageConst.PROPERTY_RETRY_TOPIC);
        if (null == retryTopic) {
            MessageAccessor.putProperty(msgExt, MessageConst.PROPERTY_RETRY_TOPIC, msgExt.getTopic());
        }
        msgExt.setWaitStoreMsgOK(false);

        int delayLevel = requestHeader.getDelayLevel();

        int maxReconsumeTimes = subscriptionGroupConfig.getRetryMaxTimes();
        if (request.getVersion() >= MQVersion.Version.V3_4_9.ordinal()) {
            maxReconsumeTimes = requestHeader.getMaxReconsumeTimes();
        }

        if (msgExt.getReconsumeTimes() >= maxReconsumeTimes
            || delayLevel < 0) {
            newTopic = MixAll.getDLQTopic(requestHeader.getGroup());
            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
            );
            if (null == topicConfig) {
                response.setCode(ResponseCode.SYSTEM_ERROR);
                response.setRemark("topic[" + newTopic + "] not exist");
                return response;
            }
        } else {
            if (0 == delayLevel) {
                delayLevel = 3 + msgExt.getReconsumeTimes();
            }

            msgExt.setDelayTimeLevel(delayLevel);
        }

        MessageExtBrokerInner msgInner = new MessageExtBrokerInner();
        msgInner.setTopic(newTopic);
        msgInner.setBody(msgExt.getBody());
        msgInner.setFlag(msgExt.getFlag());
        MessageAccessor.setProperties(msgInner, msgExt.getProperties());
        msgInner.setPropertiesString(MessageDecoder.messageProperties2String(msgExt.getProperties()));
        msgInner.setTagsCode(MessageExtBrokerInner.tagsString2tagsCode(null, msgExt.getTags()));

        msgInner.setQueueId(queueIdInt);
        msgInner.setSysFlag(msgExt.getSysFlag());
        msgInner.setBornTimestamp(msgExt.getBornTimestamp());
        msgInner.setBornHost(msgExt.getBornHost());
        msgInner.setStoreHost(this.getStoreHost());
        msgInner.setReconsumeTimes(msgExt.getReconsumeTimes() + 1);

        String originMsgId = MessageAccessor.getOriginMessageId(msgExt);
        MessageAccessor.setOriginMessageId(msgInner, UtilAll.isBlank(originMsgId) ? msgExt.getMsgId() : originMsgId);

        PutMessageResult putMessageResult = this.brokerController.getMessageStore().putMessage(msgInner);
        if (putMessageResult != null) {
            switch (putMessageResult.getPutMessageStatus()) {
                case PUT_OK:
                    String backTopic = msgExt.getTopic();
                    String correctTopic = msgExt.getProperty(MessageConst.PROPERTY_RETRY_TOPIC);
                    if (correctTopic != null) {
                        backTopic = correctTopic;
                    }

                    this.brokerController.getBrokerStatsManager().incSendBackNums(requestHeader.getGroup(), backTopic);

                    response.setCode(ResponseCode.SUCCESS);
                    response.setRemark(null);

                    return response;
                default:
                    break;
            }

            response.setCode(ResponseCode.SYSTEM_ERROR);
            response.setRemark(putMessageResult.getPutMessageStatus().name());
            return response;
        }

        response.setCode(ResponseCode.SYSTEM_ERROR);
        response.setRemark("putMessageResult is null");
        return response;
    }

    //......
}
  • consumerSendMsgBack方法会通过brokerController.getSubscriptionGroupManager().findSubscriptionGroupConfig方法查询该请求的consumerGroup对应的subscriptionGroupConfig,如果subscriptionGroupConfig为null则提前返回,如果subscriptionGroupConfig的retryQueueNums小于等于0,也提前返回;然后通过MixAll.getRetryTopic(requestHeader.getGroup())方法获取该consumerGroup对应的retryTopic,并计算queueIdInt;之后判断subscriptionGroupConfig设置的maxReconsumeTimes,如果大于等于该值则将该消息发往DLQ_GROUP_TOPIC;最后通过brokerController.getMessageStore().putMessage(msgInner)将该消息放入对应的newTopic

小结

SendMessageProcessor对于request.getCode()为RequestCode.CONSUMER_SEND_MSG_BACK会执行consumerSendMsgBack方法

doc

© 著作权归作者所有

go4it
粉丝 88
博文 1174
码字总数 1098817
作品 0
深圳
私信 提问
[RocketMQ]消息中间件—RocketMQ消息消费(三)(消息消费重试)

摘要:如果Consumer端消费消息失败,那么RocketMQ是如何对失败的异常情况进行处理? 前面两篇RocketMQ消息消费(一)/(二)篇,主要从Push/Pull两种消费模式的简要流程、长轮询机制和Consu...

morpheusWB
2018/09/29
227
0
Apache RocketMQ 4.4.0 发布

万众期待的 4.4.0 版本终于在昨天成功发布,值得关注的新特性包括权限控制(ACL)和消息轨迹(Msg Trace)。 下面大家解读该版本引入的这两大特性。 权限控制(ACL) 该特性主要为 RocketMQ 提供权...

淡漠悠然
01/24
2.4K
1
RocketMQ在windows上安装和开发使用

概述 RocketMQ是alibaba公司开源的一个纯java的开源消息中间件。 开发测试环境搭建 1. 安装&启动 进入到RocketMQ下载包解压的路径下 D:machineRocketMQ-3.0.8RocketMQ-3.0.8> 接下来安装 执行...

偶尔诗文
2015/08/25
952
2
Windows环境下搭建rocketMQ环境

下载 在官网下载安装包,然后进行解压; 安装与配置 配置环境变量 ROCKETMQ_HOME : E:rocketmq-all-4.3.2-bin-release 配置 broker.conf E:rocketmq-all-4.3.2-bin-releaseconfbroker.conf ...

晨猫
01/07
53
0
聊聊rocketmq的RequestTask

序 本文主要研究一下rocketmq的RequestTask RequestTask org/apache/rocketmq/remoting/netty/RequestTask.java 里头有一个runnable、channel以及remotingCommand NettyRemotingAbstract.pro......

go4it
2018/08/06
34
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周六乱弹 —— 不要在领导修风扇的时候打开电扇

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @巴拉迪维 :《Whats Up》 主唱妹子 Lina Perry 的嗓音实在太有力了,收放自如的自信才能唱出这么优秀的歌吧!#今日歌曲推荐# 《Whats Up》-...

小小编辑
今天
11
0
SpringBoot集成Elasticsearch并进行增删改查操作

一、创建工程 使用IntelliJ创建SpringBoot工程 SpringBoot版本为2.0.4 ElasticSearch为5.6.10 删掉蓝框中的文件(如上) 最后我们的目录结构(如下) 下面pom文件主要修改的是把spring boot从Int...

一字见心
今天
5
0
x001-版本介绍

python版本介绍 目前有2 和 3 有很多企业用的代码是2版本,随着技术的发展,以后用3的会成为大趋势 python3的安装 yum -y install wget gcc zlib-devel bzip2-devel openssl-devel ncurses-d...

侠客行之石头
今天
5
0
聊聊rocketmq的TransientStorePool

序 本文主要研究一下rocketmq的TransientStorePool TransientStorePool rocketmq-all-4.6.0-source-release/store/src/main/java/org/apache/rocketmq/store/TransientStorePool.java publi......

go4it
昨天
6
0
笔记

场外借贷, 质押 ,托管, 永续合约. 场外借贷,n签合同. 新功能 证券交易组负责中信证券机构及个人投资交易相关系统,服务机构及个人投资客户, 涉及到两融、期权、 期货、做市等境内境外创新业...

MtrS
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部