RocketMQ源码系列(四)RocketMQ消息发送,生产者producer源码篇(下)生产者发送消息流程

消息发送流程主要步骤包括:验证消息、查找路由、选择队列、消息发送。
默认是同步发送方式,超时时间是3s。

验证消息

我们通过示例中的send方法一探究竟。
在这里插入图片描述
send发送消息方法

    @Override
    public SendResult send(
        Message msg) throws MQClientException, RemotingException, MQBrokerException, InterruptedException {
    
    
        //消息验证
        Validators.checkMessage(msg, this);
        //设置topic
        msg.setTopic(withNamespace(msg.getTopic()));
        return this.defaultMQProducerImpl.send(msg);
    }

消息校验逻辑

检查topic是否合法,不能为空,并进行正则校验
长度小于127
校验是否是不能使用的topic
消息体不能为空
消息长度要大于0
检查消息体是否大于最大允许大小4M

    public static void checkMessage(Message msg, DefaultMQProducer defaultMQProducer)
        throws MQClientException {
    
    
        if (null == msg) {
    
    
            throw new MQClientException(ResponseCode.MESSAGE_ILLEGAL, "the message is null");
        }
        // 检查topic是否合法,不能为空,并进行正则校验,长度小于127
        Validators.checkTopic(msg.getTopic());
        //校验是否是不能使用的topic
        Validators.isNotAllowedSendTopic(msg.getTopic());

        // 消息体不能为空
        if (null == msg.getBody()) {
    
    
            throw new MQClientException(ResponseCode.MESSAGE_ILLEGAL, "the message body is null");
        }
        //消息大小要大于0
        if (0 == msg.getBody().length) {
    
    
            throw new MQClientException(ResponseCode.MESSAGE_ILLEGAL, "the message body length is zero");
        }
        //检查消息体是否大于最大允许大小4M
        if (msg.getBody().length > defaultMQProducer.getMaxMessageSize()) {
    
    
            throw new MQClientException(ResponseCode.MESSAGE_ILLEGAL,
                "the message body size over max value, MAX: " + defaultMQProducer.getMaxMessageSize());
        }
    }

获取路由信息

通过调用链我们可以看到最终调用sendDefaultImpl方法发送消息。
首先是查找路由信息TopicPublishInfo,通过tryToFindTopicPublishInfo方法我们可以看到,
先从topicPublishInfoTable中也就是生产者本地缓存中获取路由信息,如果存在则直接返回。
如果通过nameserver没有查找到topic对应的路由信息,则通过默认的topic去查询,如果设置自动创建topic为true, 则返回路由信息,反之则抛出无法找到topic的异常
在这里插入图片描述

    private TopicPublishInfo tryToFindTopicPublishInfo(final String topic) {
    
    
        //先从本地缓存中获取
        TopicPublishInfo topicPublishInfo = this.topicPublishInfoTable.get(topic);
        if (null == topicPublishInfo || !topicPublishInfo.ok()) {
    
    
            //本地缓存不存在则从nameserver中查找
            this.topicPublishInfoTable.putIfAbsent(topic, new TopicPublishInfo());
            this.mQClientFactory.updateTopicRouteInfoFromNameServer(topic);
            topicPublishInfo = this.topicPublishInfoTable.get(topic);
        }

        if (topicPublishInfo.isHaveTopicRouterInfo() || topicPublishInfo.ok()) {
    
    
            return topicPublishInfo;
        } else {
    
    
            /*
             * 如果通过nameserver没有查找到topic对应的路由信息,
             * 则通过默认的topic去查询,如果设置自动创建topic为true,
             * 则返回路由信息,反之则抛出无法找到topic的异常
             */
            this.mQClientFactory.updateTopicRouteInfoFromNameServer(topic, true, this.defaultMQProducer);
            topicPublishInfo = this.topicPublishInfoTable.get(topic);
            return topicPublishInfo;
        }
    }

路由信息TopicPublishInfo属性

public class TopicPublishInfo {
    
    
    //是否是顺序消息
    private boolean orderTopic = false;
    //是否有topic路由信息
    private boolean haveTopicRouterInfo = false;
    //该topic队列的消息队列
    private List<MessageQueue> messageQueueList = new ArrayList<MessageQueue>();
    //每次选择发送的队列,该值会自增1,如果该值小于0,则重置为0
    private volatile ThreadLocalIndex sendWhichQueue = new ThreadLocalIndex();
    //topic路由数据
    private TopicRouteData topicRouteData;

public class TopicRouteData extends RemotingSerializable {
    
    
    private String orderTopicConf;
    private List<QueueData> queueDatas;//队列元数据
    private List<BrokerData> brokerDatas;//topic分布的broker元数据
    //broker上过滤服务器地址列表
    private HashMap<String/* brokerAddr */, List<String>/* Filter Server */> filterServerTable;

updateTopicRouteInfoFromNameServer方法代码逻辑,如果isDefault为true,则使用默认topic去查询,如果查询到路由信息,则替换路由信息中读写队列个数为消息生产者默认的对列个数

    public boolean updateTopicRouteInfoFromNameServer(final String topic, boolean isDefault,
        DefaultMQProducer defaultMQProducer) {
    
    
        try {
    
    
            if (this.lockNamesrv.tryLock(LOCK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) {
    
    
                try {
    
    
                    TopicRouteData topicRouteData;
                    // 如果isDefault为true,则使用默认topic去查询
                    if (isDefault && defaultMQProducer != null) {
    
    
                        topicRouteData = this.mQClientAPIImpl.getDefaultTopicRouteInfoFromNameServer(defaultMQProducer.getCreateTopicKey(),
                            1000 * 3);
                        if (topicRouteData != null) {
    
    
                            //如果查询到路由信息,则替换路由信息中读写队列个数为消息生产者默认的对列个数
                            for (QueueData data : topicRouteData.getQueueDatas()) {
    
    
                                int queueNums = Math.min(defaultMQProducer.getDefaultTopicQueueNums(), data.getReadQueueNums());
                                data.setReadQueueNums(queueNums);
                                data.setWriteQueueNums(queueNums);
                            }
                        }
                    } else {
    
    
                        // 如果isDefault为false,则使用参数topic去查询
                        topicRouteData = this.mQClientAPIImpl.getTopicRouteInfoFromNameServer(topic, 1000 * 3);
                    }
                    if (topicRouteData != null) {
    
    
                        //如果查询到路由信息,则先获取本地缓存中的路由信息
                        TopicRouteData old = this.topicRouteTable.get(topic);
                        //把本地缓存的路由信息和从nameserver获取到的路由信息进行比较,是否有改变
                        boolean changed = topicRouteDataIsChange(old, topicRouteData);
                        if (!changed) {
    
    
                            changed = this.isNeedUpdateTopicRouteInfo(topic);
                        } else {
    
    
                            log.info("the topic[{}] route info changed, old[{}] ,new[{}]", topic, old, topicRouteData);
                        }
                        //如果没有发生变化则直接返回false
                        if (changed) {
    
    
                            //如果路由信息发生改变
                            TopicRouteData cloneTopicRouteData = topicRouteData.cloneTopicRouteData();
                            //更新broker地址列表
                            for (BrokerData bd : topicRouteData.getBrokerDatas()) {
    
    
                                this.brokerAddrTable.put(bd.getBrokerName(), bd.getBrokerAddrs());
                            }

                            // Update Pub info
                            {
    
    
                                //根据topicRouteData中的List<QueueData>转换成opicPublishInfo的List<MessageQueue>列表
                                TopicPublishInfo publishInfo = topicRouteData2TopicPublishInfo(topic, topicRouteData);
                                publishInfo.setHaveTopicRouterInfo(true);
                                Iterator<Entry<String, MQProducerInner>> it = this.producerTable.entrySet().iterator();
                                while (it.hasNext()) {
    
    
                                    Entry<String, MQProducerInner> entry = it.next();
                                    MQProducerInner impl = entry.getValue();
                                    if (impl != null) {
    
    
                                        //更新消息发送关于topic的路由信息
                                        impl.updateTopicPublishInfo(topic, publishInfo);
                                    }
                                }
                            }

                            // Update sub info
                            {
    
    
                                Set<MessageQueue> subscribeInfo = topicRouteData2TopicSubscribeInfo(topic, topicRouteData);
                                Iterator<Entry<String, MQConsumerInner>> it = this.consumerTable.entrySet().iterator();
                                while (it.hasNext()) {
    
    
                                    Entry<String, MQConsumerInner> entry = it.next();
                                    MQConsumerInner impl = entry.getValue();
                                    if (impl != null) {
    
    
                                        impl.updateTopicSubscribeInfo(topic, subscribeInfo);
                                    }
                                }
                            }
                            log.info("topicRouteTable.put. Topic = {}, TopicRouteData[{}]", topic, cloneTopicRouteData);
                            this.topicRouteTable.put(topic, cloneTopicRouteData);
                            return true;
                        }
                    } else {
    
    
                        log.warn("updateTopicRouteInfoFromNameServer, getTopicRouteInfoFromNameServer return null, Topic: {}", topic);
                    }
                } catch (MQClientException e) {
    
    
                    if (!topic.startsWith(MixAll.RETRY_GROUP_TOPIC_PREFIX)) {
    
    
                        log.warn("updateTopicRouteInfoFromNameServer Exception", e);
                    }
                } catch (RemotingException e) {
    
    
                    log.error("updateTopicRouteInfoFromNameServer Exception", e);
                    throw new IllegalStateException(e);
                } finally {
    
    
                    this.lockNamesrv.unlock();
                }
            } else {
    
    
                log.warn("updateTopicRouteInfoFromNameServer tryLock timeout {}ms", LOCK_TIMEOUT_MILLIS);
            }
        } catch (InterruptedException e) {
    
    
            log.warn("updateTopicRouteInfoFromNameServer Exception", e);
        }
        //如果未查到topic路由信息则返回false
        return false;
    }

默认topic会在isAutoCreateTopicEnable设置为true时,在broker上自动创建

public static final String AUTO_CREATE_TOPIC_KEY_TOPIC = "TBW102"; // Will be created at broker when isAutoCreateTopicEnable

topicRouteData2TopicPublishInfo方法

    public static TopicPublishInfo topicRouteData2TopicPublishInfo(final String topic, final TopicRouteData route) {
    
    
        TopicPublishInfo info = new TopicPublishInfo();
        info.setTopicRouteData(route);
        if (route.getOrderTopicConf() != null && route.getOrderTopicConf().length() > 0) {
    
    
            String[] brokers = route.getOrderTopicConf().split(";");
            for (String broker : brokers) {
    
    
                String[] item = broker.split(":");
                int nums = Integer.parseInt(item[1]);
                for (int i = 0; i < nums; i++) {
    
    
                    MessageQueue mq = new MessageQueue(topic, item[0], i);
                    info.getMessageQueueList().add(mq);
                }
            }

            info.setOrderTopic(true);
        } else {
    
    
            //遍历路由信息的QueueData信息
            List<QueueData> qds = route.getQueueDatas();
            Collections.sort(qds);
            for (QueueData qd : qds) {
    
    
                //如果队列有写权限
                if (PermName.isWriteable(qd.getPerm())) {
    
    
                    BrokerData brokerData = null;
                    for (BrokerData bd : route.getBrokerDatas()) {
    
    
                        //根据brokerName找到对应的brokerData
                        if (bd.getBrokerName().equals(qd.getBrokerName())) {
    
    
                            brokerData = bd;
                            break;
                        }
                    }

                    if (null == brokerData) {
    
    
                        continue;
                    }
                    // 如果不是master则继续遍历下一个
                    if (!brokerData.getBrokerAddrs().containsKey(MixAll.MASTER_ID)) {
    
    
                        continue;
                    }
                    //
                    for (int i = 0; i < qd.getWriteQueueNums(); i++) {
    
    
                        //根据topic、BrokerName、和下标创建MessageQueue
                        MessageQueue mq = new MessageQueue(topic, qd.getBrokerName(), i);
                        //填充到topicPublishInfo的List<MessageQueue>中,完成消息路由的查找
                        info.getMessageQueueList().add(mq);
                    }
                }
            }

            info.setOrderTopic(false);
        }

        return info;
    }

选择消息队列

默认机制

生产者获取到的路由信息根据brokerName和brokerId进行排序。消息发送采用重试机制,由retryTimesWhenSendFailed指定同步发送失败时重试的次数,异步重试机制在收到消息发送结果后执行回调之前进行重试。

扫描二维码关注公众号,回复: 13305982 查看本文章

选择消息队列的方法selectOneMessageQueue(final String lastBrokerName)

    public MessageQueue selectOneMessageQueue(final String lastBrokerName) {
    
    
        //lastBrokerName表示上次执行发送消息失败的broker
        if (lastBrokerName == null) {
    
    
            return selectOneMessageQueue();
        } else {
    
    
            //调用sendWhichQueue自增
            int index = this.sendWhichQueue.getAndIncrement();
            for (int i = 0; i < this.messageQueueList.size(); i++) {
    
    
                //与当前路由表中消息队列个数取模
                int pos = Math.abs(index++) % this.messageQueueList.size();
                if (pos < 0)
                    pos = 0;
                //获取对应的消息队列
                MessageQueue mq = this.messageQueueList.get(pos);
                if (!mq.getBrokerName().equals(lastBrokerName)) {
    
    
                    return mq;
                }
            }
            return selectOneMessageQueue();
        }
    }

故障延迟机制

sendLatencyFaultEnable默认为false,表示不开启故障延迟机制。
当开启消息故障机制时,首先从获取的路由信息列表中获取一个队列,判断该队列是否可用,如果可用则直接返回使用,如果不可用,则通过故障排除列表latencyFaultTolerance尝试获取一个可用的broker。根据该broker获得一个写队列数,重新选择一个消息队列。

    public MessageQueue selectOneMessageQueue(final TopicPublishInfo tpInfo, final String lastBrokerName) {
    
    
        //sendLatencyFaultEnable默认为false,表示不开启故障延迟机制
        if (this.sendLatencyFaultEnable) {
    
    
            try {
    
    
                //根据对消息队列进行轮询获取一个消息队列
                int index = tpInfo.getSendWhichQueue().getAndIncrement();
                for (int i = 0; i < tpInfo.getMessageQueueList().size(); i++) {
    
    
                    int pos = Math.abs(index++) % tpInfo.getMessageQueueList().size();
                    if (pos < 0)
                        pos = 0;
                    MessageQueue mq = tpInfo.getMessageQueueList().get(pos);
                    //验证该消息队列是否可用
                    if (latencyFaultTolerance.isAvailable(mq.getBrokerName())) {
    
    
                        if (null == lastBrokerName || mq.getBrokerName().equals(lastBrokerName))
                            return mq;
                    }
                }
                //尝试从规避的broker中选择一个可用的broker,如果没有则返回null
                final String notBestBroker = latencyFaultTolerance.pickOneAtLeast();
                int writeQueueNums = tpInfo.getQueueIdByBroker(notBestBroker);
                if (writeQueueNums > 0) {
    
    
                    final MessageQueue mq = tpInfo.selectOneMessageQueue();
                    if (notBestBroker != null) {
    
    
                        mq.setBrokerName(notBestBroker);
                        mq.setQueueId(tpInfo.getSendWhichQueue().getAndIncrement() % writeQueueNums);
                    }
                    return mq;
                } else {
    
    
                    //从不可用broker记录表中移除,重新参与路由计算
                    latencyFaultTolerance.remove(notBestBroker);
                }
            } catch (Exception e) {
    
    
                log.error("Error occurred when selecting message queue", e);
            }

            return tpInfo.selectOneMessageQueue();
        }

        return tpInfo.selectOneMessageQueue(lastBrokerName);
    }

消息发送

step1

从本地获取broker地址,如果本地缓存没有获取到broker地址,则从nameserver主动更新路由信息,再次重新获取broker地址,若还是获取不到则抛出异常。

    /**
     *
     * @param msg 待发送的消息
     * @param mq 消息发往的队列
     * @param communicationMode 消息发送的模式,同步、异步或者单向发送
     * @param sendCallback 异步发送回调函数
     * @param topicPublishInfo topic路由信息
     * @param timeout 超时时间
     * @return
     * @throws MQClientException
     * @throws RemotingException
     * @throws MQBrokerException
     * @throws InterruptedException
     */
    private SendResult sendKernelImpl(final Message msg,
        final MessageQueue mq,
        final CommunicationMode communicationMode,
        final SendCallback sendCallback,
        final TopicPublishInfo topicPublishInfo,
        final long timeout) throws MQClientException, RemotingException, MQBrokerException, InterruptedException {
    
    
        long beginStartTime = System.currentTimeMillis();
        //从本地获取broker地址
        String brokerAddr = this.mQClientFactory.findBrokerAddressInPublish(mq.getBrokerName());
        if (null == brokerAddr) {
    
    
            //如果本地缓存没有获取到broker地址,则从nameserver主动更新路由信息
            tryToFindTopicPublishInfo(mq.getTopic());
            //再次重新获取broker地址
            brokerAddr = this.mQClientFactory.findBrokerAddressInPublish(mq.getBrokerName());
        }

step2

为消息分配全局唯一ID,如果消息大小超过4k则对消息采用zip压缩,并设置消息的系统标记为MessageSysFlag.COMPRESSED_FLAG,如果是事务消息,则设置消息的系统标记为MessageSysFlag.TRANSACTION_PREPARED_TYPE

        SendMessageContext context = null;
        if (brokerAddr != null) {
    
    
            brokerAddr = MixAll.brokerVIPChannel(this.defaultMQProducer.isSendMessageWithVIPChannel(), brokerAddr);

            byte[] prevBody = msg.getBody();
            try {
    
    
                //for MessageBatch,ID has been set in the generating process
                //为消息分配全局唯一ID
                if (!(msg instanceof MessageBatch)) {
    
    
                    MessageClientIDSetter.setUniqID(msg);
                }

                boolean topicWithNamespace = false;
                if (null != this.mQClientFactory.getClientConfig().getNamespace()) {
    
    
                    msg.setInstanceId(this.mQClientFactory.getClientConfig().getNamespace());
                    topicWithNamespace = true;
                }
                //如果消息大小超过4k则对消息采用zip压缩,
                // 并设置消息的系统标记为MessageSysFlag.COMPRESSED_FLAG
                int sysFlag = 0;
                boolean msgBodyCompressed = false;
                if (this.tryToCompressMessage(msg)) {
    
    
                    sysFlag |= MessageSysFlag.COMPRESSED_FLAG;
                    msgBodyCompressed = true;
                }
                //如果是事务消息,则设置消息的系统标记为MessageSysFlag.TRANSACTION_PREPARED_TYPE
                final String tranMsg = msg.getProperty(MessageConst.PROPERTY_TRANSACTION_PREPARED);
                if (tranMsg != null && Boolean.parseBoolean(tranMsg)) {
    
    
                    sysFlag |= MessageSysFlag.TRANSACTION_PREPARED_TYPE;
                }

step3

如果注册了消息发送钩子函数,则执行消息发送之前的增强逻辑

                //如果注册了消息发送钩子函数,则执行消息发送之前的增强逻辑
                if (this.hasSendMessageHook()) {
    
    
                    context = new SendMessageContext();
                    context.setProducer(this);
                    context.setProducerGroup(this.defaultMQProducer.getProducerGroup());
                    context.setCommunicationMode(communicationMode);
                    context.setBornHost(this.defaultMQProducer.getClientIP());
                    context.setBrokerAddr(brokerAddr);
                    context.setMessage(msg);
                    context.setMq(mq);
                    context.setNamespace(this.defaultMQProducer.getNamespace());
                    String isTrans = msg.getProperty(MessageConst.PROPERTY_TRANSACTION_PREPARED);
                    if (isTrans != null && isTrans.equals("true")) {
    
    
                        context.setMsgType(MessageType.Trans_Msg_Half);
                    }

                    if (msg.getProperty("__STARTDELIVERTIME") != null || msg.getProperty(MessageConst.PROPERTY_DELAY_TIME_LEVEL) != null) {
    
    
                        context.setMsgType(MessageType.Delay_Msg);
                    }
                    this.executeSendMessageHookBefore(context);

step4

构建消息发送请求包

                //构建消息发送请求包。主要包含如下重要信息:
                /*
                 * 生产者组、topic名称、默认创建的主题key、该主题在单个broker默认队列数
                 * 队列ID(队列序号)、消息系统标记MessageSysFlag、消息发送时间、
                 * 消息标记、消息扩展属性、消息重试次数、是否批量消息等
                 */
                SendMessageRequestHeader requestHeader = new SendMessageRequestHeader();
                requestHeader.setProducerGroup(this.defaultMQProducer.getProducerGroup());
                requestHeader.setTopic(msg.getTopic());
                requestHeader.setDefaultTopic(this.defaultMQProducer.getCreateTopicKey());
                requestHeader.setDefaultTopicQueueNums(this.defaultMQProducer.getDefaultTopicQueueNums());
                requestHeader.setQueueId(mq.getQueueId());
                requestHeader.setSysFlag(sysFlag);
                requestHeader.setBornTimestamp(System.currentTimeMillis());
                requestHeader.setFlag(msg.getFlag());
                requestHeader.setProperties(MessageDecoder.messageProperties2String(msg.getProperties()));
                requestHeader.setReconsumeTimes(0);
                requestHeader.setUnitMode(this.isUnitMode());
                requestHeader.setBatch(msg instanceof MessageBatch);
                if (requestHeader.getTopic().startsWith(MixAll.RETRY_GROUP_TOPIC_PREFIX)) {
    
    
                    String reconsumeTimes = MessageAccessor.getReconsumeTime(msg);
                    if (reconsumeTimes != null) {
    
    
                        requestHeader.setReconsumeTimes(Integer.valueOf(reconsumeTimes));
                        MessageAccessor.clearProperty(msg, MessageConst.PROPERTY_RECONSUME_TIME);
                    }

                    String maxReconsumeTimes = MessageAccessor.getMaxReconsumeTimes(msg);
                    if (maxReconsumeTimes != null) {
    
    
                        requestHeader.setMaxReconsumeTimes(Integer.valueOf(maxReconsumeTimes));
                        MessageAccessor.clearProperty(msg, MessageConst.PROPERTY_MAX_RECONSUME_TIMES);
                    }
                }

step5

根据消息发送方式,同步、异步、单向方式进行网络传输。MQClientAPIImpl的sendMessage

    public SendResult sendMessage(
        final String addr,
        final String brokerName,
        final Message msg,
        final SendMessageRequestHeader requestHeader,
        final long timeoutMillis,
        final CommunicationMode communicationMode,
        final SendCallback sendCallback,
        final TopicPublishInfo topicPublishInfo,
        final MQClientInstance instance,
        final int retryTimesWhenSendFailed,
        final SendMessageContext context,
        final DefaultMQProducerImpl producer
    ) throws RemotingException, MQBrokerException, InterruptedException {
    
    
        long beginStartTime = System.currentTimeMillis();
        RemotingCommand request = null;
        String msgType = msg.getProperty(MessageConst.PROPERTY_MESSAGE_TYPE);
        boolean isReply = msgType != null && msgType.equals(MixAll.REPLY_MESSAGE_FLAG);
        if (isReply) {
    
    
            if (sendSmartMsg) {
    
    
                SendMessageRequestHeaderV2 requestHeaderV2 = SendMessageRequestHeaderV2.createSendMessageRequestHeaderV2(requestHeader);
                request = RemotingCommand.createRequestCommand(RequestCode.SEND_REPLY_MESSAGE_V2, requestHeaderV2);
            } else {
    
    
                request = RemotingCommand.createRequestCommand(RequestCode.SEND_REPLY_MESSAGE, requestHeader);
            }
        } else {
    
    
            if (sendSmartMsg || msg instanceof MessageBatch) {
    
    
                SendMessageRequestHeaderV2 requestHeaderV2 = SendMessageRequestHeaderV2.createSendMessageRequestHeaderV2(requestHeader);
                request = RemotingCommand.createRequestCommand(msg instanceof MessageBatch ? RequestCode.SEND_BATCH_MESSAGE : RequestCode.SEND_MESSAGE_V2, requestHeaderV2);
            } else {
    
    
                request = RemotingCommand.createRequestCommand(RequestCode.SEND_MESSAGE, requestHeader);
            }
        }
        request.setBody(msg.getBody());

        switch (communicationMode) {
    
    
            case ONEWAY:
                this.remotingClient.invokeOneway(addr, request, timeoutMillis);
                return null;
            case ASYNC:
                final AtomicInteger times = new AtomicInteger();
                long costTimeAsync = System.currentTimeMillis() - beginStartTime;
                if (timeoutMillis < costTimeAsync) {
    
    
                    throw new RemotingTooMuchRequestException("sendMessage call timeout");
                }
                this.sendMessageAsync(addr, brokerName, msg, timeoutMillis - costTimeAsync, request, sendCallback, topicPublishInfo, instance,
                    retryTimesWhenSendFailed, times, context, producer);
                return null;
            case SYNC:
                long costTimeSync = System.currentTimeMillis() - beginStartTime;
                if (timeoutMillis < costTimeSync) {
    
    
                    throw new RemotingTooMuchRequestException("sendMessage call timeout");
                }
                return this.sendMessageSync(addr, brokerName, msg, timeoutMillis - costTimeSync, request);
            default:
                assert false;
                break;
        }

        return null;
    }

step6

如果注册了消息发送钩子函数,执行after逻辑。

                //如果注册了消息发送钩子函数,执行after逻辑。
                // 注意,就算消息发送郭晨中发送异常该方法也会执行
                if (this.hasSendMessageHook()) {
    
    
                    context.setSendResult(sendResult);
                    this.executeSendMessageHookAfter(context);
                }

猜你喜欢

转载自blog.csdn.net/weixin_43073775/article/details/109480509