面试题:一个consumer订阅两个topic,其中一个topic消息过多堆积了,会影响另一个topic消费吗

大家好我是佩奇
发布于 2023-8-15 11:43
浏览
0收藏

该文章收录于:https://github.com/DayuMM2021/Java


无意中在网上看到这么一个问题,一个consumer订阅两个topic,其中一个topic消息过多堆积了,会影响另一个topic消费吗


对于RocketMQ这种,看源码如何方便,于是乎我就开始找相应的源码,然后一顿思考

面试题:一个consumer订阅两个topic,其中一个topic消息过多堆积了,会影响另一个topic消费吗-鸿蒙开发者社区

先给大家上结论,看堵塞的原因,如果原因是生产者瞬时产生大量的消息,比如秒杀,导致的消息堆积,基本不会影响;如果是消费者出现故障,消费速度变得奇慢无比,那就会影响,不过并不会阻塞,只是会影响速


接下来带着大家一起看源码

/**
 * Rebalance Service
 * consumer负载均衡线程服务
 */
 public class RebalanceService extends ServiceThread {}

大家先把目光聚焦到这个负载均衡的线程服务上来,这个大家也看到了,每个20秒执行一次,这个主要负载均衡的逻辑在doRebalance方法中

面试题:一个consumer订阅两个topic,其中一个topic消息过多堆积了,会影响另一个topic消费吗-鸿蒙开发者社区

我们进去这个方法看

面试题:一个consumer订阅两个topic,其中一个topic消息过多堆积了,会影响另一个topic消费吗-鸿蒙开发者社区

进来之后可以看到,对consumerTable的对象进行循环,这个存储的是所有的消费者,然后循环调用doRebalance,继续进去看

面试题:一个consumer订阅两个topic,其中一个topic消息过多堆积了,会影响另一个topic消费吗-鸿蒙开发者社区

继续往里冲

面试题:一个consumer订阅两个topic,其中一个topic消息过多堆积了,会影响另一个topic消费吗-鸿蒙开发者社区

线程的创建来到这里,我们可以看到核心处理是这个rebalanceByTopic,传入的参数就是我们这个消费者监听的topic

面试题:一个consumer订阅两个topic,其中一个topic消息过多堆积了,会影响另一个topic消费吗-鸿蒙开发者社区

这里的mqSet是该topic的所有consumerqueue,也就是默认创建的那4个队列,当然,这个数量可以改变  


然后我们可以看到allocateMessageQueueStrategy,这个是一个分配策略对象,调用其中的allocate来进行分配该topic的消息队列

面试题:一个consumer订阅两个topic,其中一个topic消息过多堆积了,会影响另一个topic消费吗-鸿蒙开发者社区

这个分配策略也有几种实现方式,大家看一看,根据名字其实大家也可以猜个八九不离十了,感兴趣的可以点进去看看详细的处理机制

面试题:一个consumer订阅两个topic,其中一个topic消息过多堆积了,会影响另一个topic消费吗-鸿蒙开发者社区

分配好之后,将队列赋值给allocateResultSet这个对象,这里为啥要用set集合存储呢


我的个人猜测是,防止出现queue数量的重新改变的情况下,可能导致这里出现重复,这里增加一层set防止这种极端情况的出现


接下来分配好队列之后,主要的处理就是updateProcessQueueTableInRebalance,这个就是负责更新消息队列,其实呢,也可以认为成把这个消费者需要负责的这些队列赋值给它,也就是这是你的责任了,你这个消费者需要处理这些队列

面试题:一个consumer订阅两个topic,其中一个topic消息过多堆积了,会影响另一个topic消费吗-鸿蒙开发者社区

我们进来updateProcessQueueTableInRebalance这个方法之后,上面的那些我就折叠起来不给大家看了,这里的处理主要也是针对于某些机器突然宕机或者增加一些机器的情况


这个方法的主要处理是在最后这个拉取请求这里,也就是dispatchPullRequest这个,传入的参数是一个pullRequest的list

面试题:一个consumer订阅两个topic,其中一个topic消息过多堆积了,会影响另一个topic消费吗-鸿蒙开发者社区

线程的创建进来之后,循环处理pullRequest,哎,还没找到最底层,继续点进去

面试题:一个consumer订阅两个topic,其中一个topic消息过多堆积了,会影响另一个topic消费吗-鸿蒙开发者社区

线程的创建哎。终于找到你了,就是你这个家伙,最后就执行了一个put方法,放进去的就是一个LinkedBlockingQueue队列

面试题:一个consumer订阅两个topic,其中一个topic消息过多堆积了,会影响另一个topic消费吗-鸿蒙开发者社区

这个是一个拉取消息的请求队列,请求的对象就是pullRequest


实际处理的时候,也就是拉取消息的时候,多个线程会从LinkedBlockingQueue中去take消息,然后按照放入的顺序去进行消费

面试题:一个consumer订阅两个topic,其中一个topic消息过多堆积了,会影响另一个topic消费吗-鸿蒙开发者社区

给大家解释一下这个流程,这里就是rocketmq首先对消息会进行一个负载均衡Rebalance的过程,这个就是将topic中的consumerqueue队列按照consumer进行分配,分配策略就是上面看到的那几种


将pullRequest放入到这个LinkedBlockingQueue中,这里放的是topic、brokerName、queueID这些,这个时候已经排好了后面消费的顺序了


比如有10个request中,大概5个是topicTest1,另外5个是topicTest2


所以呢,这个时候假如topicTest1消息堆积了,还是会照常去消费topicTest2的,此时我们需要看这个堆积的原因,如果堆积是因为秒杀一类的场景导致瞬时间产生大量消息,这样消费者还是会正常消费topicTest1,所以不会影响topicTest2


但是,如果topicTest1消费速度很慢,导致所有线程都处理很慢,都被占了,那样就会稍微影响topicTest2的速度了,不过那也只是暂时的,不会阻塞topicTest2的




文章转载自公众号:左耳君

分类
已于2023-8-15 11:43:35修改
收藏
回复
举报
回复
    相关推荐