Rocketmq 4.3.2消息发送逻辑--------sendDefaultImpl方法研究

消息发送逻辑

makeSureStateOK():判断服务(serviceState)是否可用,不可用就直接退出
checkMessage: 判断消息是否符合要求:是否为空,topic(还要判断topic是否符合命名规则),body是否为空,消息长度是否为0或者大于默认消息长度。
在这里插入图片描述
beginTimestampFirst记录当前时间戳,表明timeout从此刻开始计时。
tryToFindTopicPublishInfo:获取topic路由信息
在这里插入图片描述
进入tryToFindTopicPublishInfo()方法:
如果缓存中topic不存在或者没有可用的topic,那就去nameserver中去找topic。

在这里插入图片描述
进入updateTopicRouteInfoFromNameServer,尝试锁住nameserver,若未获得锁,等待3000毫秒后依旧没有获得锁就返回false,获得锁后,就开始在nameserver上找topic。
在这里插入图片描述
如果满足传进来的参数isDefault为true以及defaultMQProducer不为空,那么就用rocketmq默认的一个topic: TBW102的TopicRouteData变量来构造TopicPublishInfo对象
在这里插入图片描述
如果不满足的话就根据传进来的topic参数到nameserver里去查这个topic的信息。
进入getTopicRouteInfoFromNameServer方法中:设置请求头中的Topic参数后,发送获取Topic路由信息的request请求给NameServer (invokeSync???对rocketmq的rpc通信框架还没了解,这里就不深入了)假如获取Topic存在,则成功返回,利使用TopicRouteData进行解码,且直接返回
在这里插入图片描述

返回的TopicRouteData不为空的话,进入topicRouteDataIsChange方法,判断新获得的topicRouteData与本地的老的topicRouteData是否发生变化。
在这里插入图片描述
如果变化则克隆,在brokerAddrTable中放置新的topicRouteData里记载的brokername和对应的brokeraddr。
在这里插入图片描述
将TopicRouteData转换至TopicPublishInfo路由信息以及TopicSubscribeInfo路由信息
在这里插入图片描述

在这里插入图片描述
(此图来源博客:https://www.songma.com/news/txtlist_i4045v.html)
在这里插入图片描述
进入selectOneMessageQueue()方法:
情况一:发送消息推迟容错开关打开
重点:重试时,优先选择的broker是一个可用的而且等于lastBrokerName的broker
在这里插入图片描述
进入getSendWhichQueue().getAndIncrement()方法,可能看到index的产生机制:
在这里插入图片描述
所以整个过程大致如下:选择一个queue来发消息,如果之前没有发送过消息,随机选择一个,如果发过消息,选择上一次发送记录的queue的下一个queue。判断所选择的的mq的broker,如果可用isAvailable,则看跟lastBrokerName(消息重发时就会有lastBrokerName的记录)是否一致或者lastBrokerName是否为null,如果满足条件,就选择这个mq,如果这个queue不符合条件,就再判断下下一个queue,直到遍历该topic的所有queue。
如果找不到符合上面要求的broker,那么就那么就放弃broker==lastBrokerName这个条件, 选择一个相对较好的broker来发送pickOneAtLeast()
在这里插入图片描述
在这里插入图片描述
找到可以用来发送的mq后,调用sendKernelImpl开始发送消息。
在这里插入图片描述
异步和ONEWAY模式直接返回,同步的话还得判断消息是否发送成功,发送失败后得重新发送。
在这里插入图片描述

发送重试

这里为了更好的说明消息发送重试的机制,我们先来看一下MQFaultStrategy这个类。
我们需要来了解下LatencyFaultToleranceImpl这个类,以及它的一些相关方法。
在这里插入图片描述
在这里插入图片描述LatencyFaultToleranceImpl
首先我们可以看到LatencyFaultToleranceImpl接口里有一个叫faultItemTable的hashmap数据结构,储存着broker和它对应的一些信息,我们先进入FaultItem看看都是哪些信息。
在这里插入图片描述
结合函数updateFaultItem,我们可以了解到FaultItem的三个属性,分别是brokername,延迟容忍时长,以及broker不可用时长结束的时刻。
在这里插入图片描述
在这里插入图片描述
即可知faultItemTable这个hashmap中,如果元素FaultItem不为空,则表明记录过延迟容错的相关信息,为null则表明该broker还没有出错,即可用。这也是判断broker是否可用的方法isAvailable
在这里插入图片描述
当FaultItem != null时,还需要判断不可用时长是否已经过了,即当前时刻是否大于startTimestamp,如果满足条件,也可认为该broker是可用的。
在这里插入图片描述
接下来我们来看一下发送重试时找不是最好的broker的那个方法pickOneAtLeast。
在这里插入图片描述
可以看出,pickOneAtLeast()的实现机制是:将faultItemTable里记录的所有broker打乱随机排序后再按一定规则进行排序,每次随机找broker的话是在排序后的broker list 的前一半broker中找。
排序规则如何呢,我们可以看到FaultItem实现Comparable接口,Comparable接口中有一个int compareTo(T o)方法,调用这个方法的对象将会与参数o进行比较,小于o、等于o和大于o分别对应的返回值为负数、0和正数。
我们看一下FaultItem里的compareTo(final FaultItem other)方法:
在这里插入图片描述
可以看出排序规则如下:可用的broker排在不可用的broker前面,延迟容忍时间长的排在延迟容忍时间短的broker前面,不可用时长短的排在不可用时长长的broker前面。

猜你喜欢

转载自blog.csdn.net/qq_34770694/article/details/85245431
今日推荐