Search in sources :

Example 1 with ConsumerSendMsgBackRequestHeader

use of org.apache.rocketmq.common.protocol.header.ConsumerSendMsgBackRequestHeader in project rocketmq by apache.

the class SendMessageProcessor method consumerSendMsgBack.

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);
    if (this.hasConsumeMessageHook() && !UtilAll.isBlank(requestHeader.getOriginMsgId())) {
        ConsumeMessageContext context = new ConsumeMessageContext();
        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;
}
Also used : RemotingCommand(org.apache.rocketmq.remoting.protocol.RemotingCommand) ConsumeMessageContext(org.apache.rocketmq.broker.mqtrace.ConsumeMessageContext) MessageExt(org.apache.rocketmq.common.message.MessageExt) PutMessageResult(org.apache.rocketmq.store.PutMessageResult) ConsumerSendMsgBackRequestHeader(org.apache.rocketmq.common.protocol.header.ConsumerSendMsgBackRequestHeader) MessageExtBrokerInner(org.apache.rocketmq.store.MessageExtBrokerInner) TopicConfig(org.apache.rocketmq.common.TopicConfig) SubscriptionGroupConfig(org.apache.rocketmq.common.subscription.SubscriptionGroupConfig)

Example 2 with ConsumerSendMsgBackRequestHeader

use of org.apache.rocketmq.common.protocol.header.ConsumerSendMsgBackRequestHeader in project rocketmq-rocketmq-all-4.1.0-incubating by lirenzuo.

the class SendMessageProcessor method consumerSendMsgBack.

// Broker Consumer将处理不了的消息发回服务器
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);
    // 消息轨迹:记录消费失败的消息
    if (this.hasConsumeMessageHook() && !UtilAll.isBlank(requestHeader.getOriginMsgId())) {
        // 执行hook
        ConsumeMessageContext context = new ConsumeMessageContext();
        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;
    }
    // 检查Broker权限
    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;
    }
    // 如果重试队列数目为0,则直接丢弃消息
    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();
    // 如果是单元化模式,则对 topic 进行设置
    int topicSysFlag = 0;
    if (requestHeader.isUnitMode()) {
        topicSysFlag = TopicSysFlag.buildSysFlag(false, true);
    }
    // 检查topic是否存在
    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;
    }
    // 检查topic权限
    if (!PermName.isWriteable(topicConfig.getPerm())) {
        response.setCode(ResponseCode.NO_PERMISSION);
        response.setRemark(String.format("the topic[%s] sending message is forbidden", newTopic));
        return response;
    }
    // 查询消息,这里如果堆积消息过多,会访问磁盘
    // 另外如果频繁调用,是否会引起gc问题,需要关注 TODO
    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
    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);
    // 保存源生消息的 msgId
    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:
                // 统计失败重试的Topic
                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;
}
Also used : RemotingCommand(org.apache.rocketmq.remoting.protocol.RemotingCommand) ConsumeMessageContext(org.apache.rocketmq.broker.mqtrace.ConsumeMessageContext) MessageExt(org.apache.rocketmq.common.message.MessageExt) PutMessageResult(org.apache.rocketmq.store.PutMessageResult) ConsumerSendMsgBackRequestHeader(org.apache.rocketmq.common.protocol.header.ConsumerSendMsgBackRequestHeader) MessageExtBrokerInner(org.apache.rocketmq.store.MessageExtBrokerInner) TopicConfig(org.apache.rocketmq.common.TopicConfig) SubscriptionGroupConfig(org.apache.rocketmq.common.subscription.SubscriptionGroupConfig)

Example 3 with ConsumerSendMsgBackRequestHeader

use of org.apache.rocketmq.common.protocol.header.ConsumerSendMsgBackRequestHeader in project rocketmq-rocketmq-all-4.1.0-incubating by lirenzuo.

the class SendMessageProcessorTest method createSendMsgBackCommand.

private RemotingCommand createSendMsgBackCommand(int requestCode) {
    ConsumerSendMsgBackRequestHeader requestHeader = new ConsumerSendMsgBackRequestHeader();
    requestHeader.setMaxReconsumeTimes(3);
    requestHeader.setDelayLevel(4);
    requestHeader.setGroup(group);
    requestHeader.setOffset(123L);
    RemotingCommand request = RemotingCommand.createRequestCommand(requestCode, requestHeader);
    request.makeCustomHeaderToNet();
    return request;
}
Also used : RemotingCommand(org.apache.rocketmq.remoting.protocol.RemotingCommand) ConsumerSendMsgBackRequestHeader(org.apache.rocketmq.common.protocol.header.ConsumerSendMsgBackRequestHeader)

Example 4 with ConsumerSendMsgBackRequestHeader

use of org.apache.rocketmq.common.protocol.header.ConsumerSendMsgBackRequestHeader in project rocketmq-rocketmq-all-4.1.0-incubating by lirenzuo.

the class MQClientAPIImpl method consumerSendMessageBack.

public void consumerSendMessageBack(final String addr, final MessageExt msg, final String consumerGroup, final int delayLevel, final long timeoutMillis, final int maxConsumeRetryTimes) throws RemotingException, MQBrokerException, InterruptedException {
    ConsumerSendMsgBackRequestHeader requestHeader = new ConsumerSendMsgBackRequestHeader();
    RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.CONSUMER_SEND_MSG_BACK, requestHeader);
    requestHeader.setGroup(consumerGroup);
    requestHeader.setOriginTopic(msg.getTopic());
    requestHeader.setOffset(msg.getCommitLogOffset());
    requestHeader.setDelayLevel(delayLevel);
    requestHeader.setOriginMsgId(msg.getMsgId());
    requestHeader.setMaxReconsumeTimes(maxConsumeRetryTimes);
    RemotingCommand response = this.remotingClient.invokeSync(MixAll.brokerVIPChannel(this.clientConfig.isVipChannelEnabled(), addr), request, timeoutMillis);
    assert response != null;
    switch(response.getCode()) {
        case ResponseCode.SUCCESS:
            {
                return;
            }
        default:
            break;
    }
    throw new MQBrokerException(response.getCode(), response.getRemark());
}
Also used : RemotingCommand(org.apache.rocketmq.remoting.protocol.RemotingCommand) ConsumerSendMsgBackRequestHeader(org.apache.rocketmq.common.protocol.header.ConsumerSendMsgBackRequestHeader) MQBrokerException(org.apache.rocketmq.client.exception.MQBrokerException)

Example 5 with ConsumerSendMsgBackRequestHeader

use of org.apache.rocketmq.common.protocol.header.ConsumerSendMsgBackRequestHeader in project rocketmq by apache.

the class MQClientAPIImpl method consumerSendMessageBack.

public void consumerSendMessageBack(final String addr, final MessageExt msg, final String consumerGroup, final int delayLevel, final long timeoutMillis, final int maxConsumeRetryTimes) throws RemotingException, MQBrokerException, InterruptedException {
    ConsumerSendMsgBackRequestHeader requestHeader = new ConsumerSendMsgBackRequestHeader();
    RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.CONSUMER_SEND_MSG_BACK, requestHeader);
    requestHeader.setGroup(consumerGroup);
    requestHeader.setOriginTopic(msg.getTopic());
    requestHeader.setOffset(msg.getCommitLogOffset());
    requestHeader.setDelayLevel(delayLevel);
    requestHeader.setOriginMsgId(msg.getMsgId());
    requestHeader.setMaxReconsumeTimes(maxConsumeRetryTimes);
    RemotingCommand response = this.remotingClient.invokeSync(MixAll.brokerVIPChannel(this.clientConfig.isVipChannelEnabled(), addr), request, timeoutMillis);
    assert response != null;
    switch(response.getCode()) {
        case ResponseCode.SUCCESS:
            {
                return;
            }
        default:
            break;
    }
    throw new MQBrokerException(response.getCode(), response.getRemark());
}
Also used : RemotingCommand(org.apache.rocketmq.remoting.protocol.RemotingCommand) ConsumerSendMsgBackRequestHeader(org.apache.rocketmq.common.protocol.header.ConsumerSendMsgBackRequestHeader) MQBrokerException(org.apache.rocketmq.client.exception.MQBrokerException)

Aggregations

ConsumerSendMsgBackRequestHeader (org.apache.rocketmq.common.protocol.header.ConsumerSendMsgBackRequestHeader)6 RemotingCommand (org.apache.rocketmq.remoting.protocol.RemotingCommand)6 ConsumeMessageContext (org.apache.rocketmq.broker.mqtrace.ConsumeMessageContext)2 MQBrokerException (org.apache.rocketmq.client.exception.MQBrokerException)2 TopicConfig (org.apache.rocketmq.common.TopicConfig)2 MessageExt (org.apache.rocketmq.common.message.MessageExt)2 SubscriptionGroupConfig (org.apache.rocketmq.common.subscription.SubscriptionGroupConfig)2 MessageExtBrokerInner (org.apache.rocketmq.store.MessageExtBrokerInner)2 PutMessageResult (org.apache.rocketmq.store.PutMessageResult)2