RocketMQ源码解析——Producer部分之消息发送过程DefaultMQProducer到DefaultMQProducerImpl(1)

发送消息入口DefaultMQProducer

前面说了RocketMQ消息生产者的启动逻辑,现在接着说对应的消息发送的逻辑。消息发送的入口在DefaultMQProducer类的send方法。这个方法有很多的重载方法对应的参数各不一样这里举例其中参数最多的方法进行说明

public void send(Collection<Message> msgs, MessageQueue mq, SendCallback sendCallback, long timeout)

方法的参数分别说明一下:

参数 类型 说明
msgs Message 消息对象
mq MessageQueue 发送指定指定的queue
sendCallback SendCallback 发送回调方法
timeout long 超时时间

消息发送实现DefaultMQProducerImpl

send方法对应的实现直接委托给了DefaultMQProducerImpl实现具体的细节。这个类中有两个默认的发送消息的实现,一个是同步的一个是异步的。两者的区别其实很简单,异步相对同步方法来说多了一个自定义回调实现。看一下两者对比

//异步实现
public void send(Message msg,
        SendCallback sendCallback) throws MQClientException, RemotingException, InterruptedException {
   
        send(msg, sendCallback, this.defaultMQProducer.getSendMsgTimeout());
    }
    
//同步实现   
public SendResult send(
        Message msg) throws MQClientException, RemotingException, MQBrokerException, InterruptedException {
   
		//默认消息超时时间3000毫秒,也就是5分钟
        return send(msg, this.defaultMQProducer.getSendMsgTimeout());
    }

但是两个方法的底层调用的还是同一个方法sendDefaultImpl。这个方法也是我们要重点分析的对象。先简单说一下方法的入参都是什么。

参数 参数类型 说明
msg Message 消息信息封装对象
communicationMode CommunicationMode 消息发送类型,同步或者异步
sendCallback SendCallback 异步发送模式下的回调函数
timeout long 消息发送超时时间
发送消息主方逻辑实现 sendDefaultImpl

这里只把正常逻辑的代码列出来,异常相关的逻辑忽略

private SendResult sendDefaultImpl(
        Message msg,
        final CommunicationMode communicationMode,
        final SendCallback sendCallback,
        final long timeout
    ) throws MQClientException, RemotingException, MQBrokerException, InterruptedException {
   
		//确认客户端的状态
        this.makeSureStateOK();
		/**
		 * 消息校验,包含消息的topic校验和消息体的校验。
		 *  topic校验包含以下几点,topic的名字,长度以及是否为不准用的topic(SCHEDULE_TOPIC_XXXX)
		 *  消息体校验 消息体是不是空和消息体的长度
		 */

        Validators.checkMessage(msg, this.defaultMQProducer);
		//这次调用的id
        final long invokeID = random.nextLong();
        //开始时间戳
        long beginTimestampFirst = System.currentTimeMillis();
        long beginTimestampPrev = beginTimestampFirst;
        long endTimestamp = beginTimestampFirst;
        //从topic配置缓存中查找对应的已经发布的topic,这里可能会去nameServer去拉取配置
        TopicPublishInfo topicPublishInfo = this.tryToFindTopicPublishInfo(msg.getTopic());
		//配置不为null,并且配置有效
        if (topicPublishInfo != null && topicPublishInfo.ok()) {
   
            boolean callTimeout = false;
            MessageQueue mq = null;
            Exception exception = null;
            SendResult sendResult = null;
            //交互模式是同步,那么失败重试的次数是默认的配置次数(默认为2)+1,如果是异步失败重试次数是1
            int timesTotal = communicationMode == CommunicationMode.SYNC ? 1 + this.defaultMQProducer.getRetryTimesWhenSendFailed() : 1;
            int times = 0;
            //记录重试时候发送消息目标Broker名字的数组
            String[] brokersSent = new String[timesTotal];
			//进行重试次数的循环发送消息逻辑
            for (; times < timesTotal; times++) {
   
            	//获取broker的名字,第一次为null,第二次为上次选择的broker名字
                String lastBrokerName = null == mq ? null : mq.getBrokerName();
                //根据topic配置选择一个MessageQueue
                MessageQueue mqSelected = this.selectOneMessageQueue(topicPublishInfo, lastBrokerName);
				//如果
                if (mqSelected != null) {
   
                    mq = mqSelected;
                    //添加选择的broker名称到已选集合中
                    brokersSent[times] = mq.getBrokerName();
                    try {
   
                        beginTimestampPrev = System.currentTimeMillis();
						//重试的次数之内,需要设置消息的topic
                        if (times > 0) {
   
                            //Reset topic with namespace during resend.
                            msg.setTopic(this.defaultMQProducer.withNamespace(msg.getTopic()));
                        }
                        long costTime = beginTimestampPrev - beginTimestampFirst;
						//这里的timeout,超时时间默认是3000毫秒
                        if (timeout < costTime) {
   
                            callTimeout = true;
                            break
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值