RocketMQ源码解析之namesrv(获取topic信息)

原创不易,转载请注明出处


前言

我们在《RocketMQ源码解析之namesrv启动流程》介绍namesrv的时候,说过消息生产者与消息消费者要向namesrv获取topic信息,不然的话消息消费者和消息生产者不知道要把消息发个哪个broker 或者是不知道找哪个broker 要消息进行消费,本文将介绍下namesrv是如何处理消息消费者或者消息生产者获取topic 请求的。

1. 回顾消息生产者向namesrv获取topic信息

消息生产者有两个事件来触发向namsrv获取topic信息,第一个是消息生产者启动的时候,会创建一个定时任务,然后每隔30s向namesrv获取一下最新的topic信息,获取回来后更新下本地的缓存,第二个是发送消息的时候,会根据消息里面的那个topic信息,然后去本地缓存中获取一下这个topic 的信息,如果没有获取到的话,就会去namesrv获取一下这个topic信息,并更新到本地缓存中,然后在去本地缓存获取一遍。
其实说了这么多获取topic信息,那么这个topic信息到底是什么呢?在消息生产者中是TopicPublishInfo ,你可以把它简单的理解为,这个topic 有几个MessageQueue 然后每个MessageQueue 分到那个broker 上了,里面有broker的name 与地址,这样子后面会根据一定的算法选出一个合适的MessageQueue,才能知道这个MessageQueue在哪个broker上,这个broker的地址是什么。
我们来看下消息生产者向namesrv获取topic的源码,这里就从发送消息获取topic信息开始解析。

TopicPublishInfo topicPublishInfo = this.tryToFindTopicPublishInfo(msg.getTopic());

在这里插入图片描述
我们可以看到先从本地缓存中获取,如果没有找到的话,就会调用updateTopicRouteInfoFromNameServer方法,这个方法太长了,我们直接把重要的代码贴上
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里需要重点注意的就是画红框的RequestCode.GET_ROUTEINTO_BY_TOPIC, 这个code后面我们解析namesrv获取到这个请求的时候会用到,接着就是调用netty客户端进行发送了,需要注意的时候这个是同步调用。
好了,关于消息生产者向namesrv获取topic信息的源码我们解析完了,因为这部分我们在介绍消息生产者的时候有一篇文章专门介绍过
RocketMQ源码解析之消息生产者(获取topic路由信息)

2. namesrv处理获取topic信息请求

我们在介绍namesrv 启动的时候,有注册processor这么一个步骤,namesrv到达的内容,如果是请求类型的话,就会交给这个DefaultRequestProcessor这个processor来处理
在这里插入图片描述
code是RequestCode.GET_ROUTEINTO_BY_TOPIC,我们接着来看看getRouteInfoByTopic方法
在这里插入图片描述
这个方法首先是创建response,解析请求header,将topic 交给RouteInfoManager 的pickupTopicRouteData 方法获取topic对应的TopicRouteData,如果获取到的不是null的话,就序列化,然后塞到response中,设置响应code,最后返回。这里我们要关注下RouteInfoManager的pickupTopicRouteData 方法。在看这个方法之前,我们先看下RouteInfoManager 里面的那几个成员变量map
在这里插入图片描述
topicQueueTable缓存的是 topic 与queuedata 集合信息对应关系,queuedata 其实里面记录着这个topic 分成几个readQueue,几个writeQueue,然后这个queue 是在哪个broker上面存储着
在这里插入图片描述
brokerAddrTable这个缓存着 broker name 与 brokerData对应关系,这个brokerData 里面有集群名字,broker name ,还有broker id 与地址对应关系,其实就是broker name 与 这个broker name 下面的所有broker地址
在这里插入图片描述
clusterAddrTable这个map缓存着 集群名 与 这个集群对应 broker name的这么一个关系。
brokerLiveTable这个map 缓存着 每个broker 与它的心跳状态,比如说某个broker 向namesrv发送心跳注册,然后就会更新这个map里面对应的数据。
filterServerTable这个map缓存着每个broker 与对应filter server 集合的一个信息。
其实这个pickupTopicRouteData 方法其实就是从这堆map 中找数据然后封装成TopicRouteData 对象。
在这里插入图片描述
我们看下这个TopicRouteData ,有个 queueData集合,有个 brokerData集合,还有个filterServer集合,QueueData,BrokerData ,filter我们都有介绍过。可以想想从哪几个map中获取到这些信息,前提是你知道topic
可以从topicQueueTable 获取 这个topic 对应的QueueData集合,因为QueueData 对象中有个broker name, 就可以遍历QueueData集合 ,然后根据某个QueueData 对象获取到对应的broker name ,根据broker name 从brokerAddrTable 缓存中获取到对应的 BrokerData对象放到brokerData集合中,同时也从BrokerData 对象中获取到一堆broker 地址,根据broker 地址 从filterServerTable 缓存中获取到对应的filter集合塞到filterServerTable 中,好了这样就把TopicRouteData 对象所需要的凑齐了,我们来看下源码
在这里插入图片描述
可以发现源码也是这个逻辑,先从topicQueueTable 获取 QueueData集合 ,然后遍历将QueueData集合 里面的broker name 放到set集合中,然后遍历set集合,根据broker name 从brokerAddrTable 获取BrokerData对象信息,然后从BrokerData对象中获取broker addr 们,然后再遍历broker addr 们,根据broker addr 从filterServerTable 获取对应filter。
好了,到这namesrv处理获取topic信息请求就解析完成了,至于这些缓存中的信息怎么来的,我们介绍broker 向namesrv注册的时候就能知道了。

总结

本篇我们先是回顾了消息生产者向namesrv获取topic 的流程,又介绍了namesrv处理获取topic信息请求的流程,所谓获取的topic信息其实就是 这个topic 有多少 queue,然后每个queue存储在哪个broker name上面,broker name 对应的broker 机器地址又有哪些,就是这个topic对应的queue 分别在哪些机器上,知道这些后,消息生产者与消息消费者就能找到具体机器进行发送消息与消费消息了,关于namesrv上面那几个缓存map数据的来源,我们介绍broker 向namesrv注册的时候就知道了,其实就是broker向namesrv注册的时候带过去的。

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页