RocketMQ之Push Consumer一点阅读分析

139 阅读3分钟

背景描述

近日做项目用到Rocket-MQ,发现Consumer配置有pull和push两种方式,pull其实还好理解,就是push乍一听,感觉怪怪的,便想到阅读源码理解一下,话不多说正式开始

结论先行

正式开始之前,先列出几个几个问题及结论:

  • 1. 默认消费方式采用的是push
  • 2. push消费机制是通过注册监听器进行消息消费
  • 3. push机制也会进行pull消费

正式入戏

通过查看源码包结构,定义出了看起来像是对应的类,DefaultMQPushConsumerDefaultMQPullConsumer,后者改日再聊,先看下前者

定位结论1

看了一下结构,便开始查看构造方法,发现 image.png 这个构造方法有相对应的usage,便定位到对应的位置去,一下就定位到了RocketMQConsumerFactory.initPushConsumer方法,唉,粗略喵一眼,看到还有一个对应的RocketMQConsumerFactory.initPullConsumer方法,这不正好对应push和pull两种模式嘛。说干就干,这两个发方法断点一下,看默认进的那个,通过debug发现进了initPushConsumer方法。

好,此时得出第一个重要结论:RocketMQ默认采用push消费模式

找找结论2

来吧,接下来又来了解下push模式是咋运行的,通过官网和百度google发现是broker主动发消息给consumer,可我没看到啊,于是就开始定位代码,于是找initPushConsumer的usage,唉,又轻轻松松发现了 image.png 下面两个判断很明显,是判断push订阅的是普通消息还是顺序消息,很明显我们就是普通消息嘛,于是看下面,看到consumerMessage方法,进去,立马发现了下面的 image.png 我们接着看,注册的监听器在哪使用的,于是便一点点查usage,发现在ConsumeMessageService的实现类,都用到了注册的监听器来进行消费,这里以用的最多的ConsumeMessageConcurrentlyService为例 image.png 方法名顾名思义就知道是直接消费消息调用的,接着便一步一步查usage image.png 到这里来了,很明显,一个是client,一个是server,应该进哪个去看呢?因为我们是消费的客户端,所以我选择进入client查看 image.png 接着, 就进入到了这里,这个就很明显了,是客户端实例初始化到时候调用,后面想都能想到,肯定是DefaultPushConsumer初始化到时候对调用该方法

到这里,第二个结论也应证了。

看能不能编出来结论3

通过观察DefaultMQPushConsumer发现了一个特别的属性 image.png 这不是push方式吗?咋还会用到pull?不应该有一个pushInterval吗?于是又开始查usage 发现设置这个属性值,来源于这里 image.png image.png 然后接着看,啥时候会用到 image.png 一看,像那么回事,进去看看,DefaultMQPushConsumerImpl越来越像那么回事啊,默认MQ推送消费实现类,但一看所在的位置 image.png 这里稍稍解析下为啥这个pullInterval会在onSuccess中使用,我的理解是,成功之后会根据条件判断是理解之行拉取消息操作还是延迟多久之后进行拉取操作,另外,这个所在的pullMessage方法也是在需要重试的时候才会调用 有点让人难以接受,为啥会是pullMessage方法啊?不应该是pushMessage方法吗?说好的push呢?然后又继续捞usage image.png 追到了PullMessageService的run方法,发现这里面在从messageRequestQueue里面取消息来进行拉取,然后又去找哪里往队列里塞的呢? 经过一步步的usage查找,最终找到了在客户端启动时执行的任务,找到了对应的引用,即消费失败重试的时候会用到 image.png

到这里,三个结论终于找到了出处。

过程没有完整贴上来,因为涉及的源码太多了,不过我每个截图,都把对应的class贴上来了,大家可以大致跟着响应的class和method定位到具体的流程,可能有些不完善的,欢迎大家提建议。