RocketMQ源码学习 (五) 消费者-消费者拉消息原理学习

消费者拉消息的流程和负载均衡息息相关,建议在学习该内容的时候先去了解一下消费者的负载均衡。在负载均衡方法的最后,将创建的PullRequest对象转交给PullMessageService(拉取消息服务),本文就以PullMessageService为开始叙述消费者拉取消息的流程。

1 PullMessageService

PullMessageService是在客户端实例MQClientInstance里面启动的一个服务,在客户端实例启动阶段就会将该服务启动起来,PullMessageService继承自ServiceThread,里面有自己的线程,该线程启动后会基于PullMessageService里面的阻塞队列queue做相关工作,该queue里面的每个对象就是PullRequest对象,基于这些信息可以发起拉消息的请求。
PullMessageService类的主要组成

负载均衡之后当有新的PullRequest对象产生之后,放入阻塞队列中,当有新的对象进入之后就会将其拿出来进入pullMessage方法里拉消息。pullMessage方法具体实现在DefaultMQPushConsumerImpl消费者实现类里面,接下来就看该方法的相关操作

2 消费者实现类DefaultMQPushConsumerImpl里面的pullMessage方法

2.1 pullMessage方法主题流程

该方法的具体流程如下:
在这里插入图片描述

2.2 sysFlag字段说明

sysFlag的内容如下:该bit位不同位表示了不同的参数,如最后一位表示是否提交本地Offset倒数第二位表示是否开启长轮询,因为如果不开启,当没有相关消息可以消费的时候会疯狂去轮询,长轮询时间是15秒。倒数第三位:消费者在启动和心跳的时候都会消费者订阅信息同步到服务器,所以一般这里是0,可以减轻io的压力;倒数第四位:一般默认为tag过滤,因此该位一般为0。

2.3 PullCallback方法

PullCallback类的具体内容如下:该方法在InvokeCallback调用。

无效的offset是指没有命中MinOffset和MaxOffset区间,如果变这个区间,则会给出推荐值MaxOffset或者MinOffset

在这里插入图片描述
该队列岂不没有消费者去消费了?
答:是的,但是很快就有消费者去消费它了,想想前面聊过的负载均衡程序,每时隔20秒,会进行一-次
rbl,下次rbl时, 该队列就会被分配到某个消费者了,rbl程序会再次为该队列创建processQueue,再
次为该队列创建PullRequest,该pullRequest会再被加入到PullMessageService任务队列。

2.4 processPullResult方法

上图中的与处理结果的方法在PullAPIWrapper中的processPullResult方法的内容如下:
在这里插入图片描述

追加属性的字段从PullResult对象中获取;

① 在Success方法中获取到与处理结果后的几个分支里,CHECK:pullStatus==FOUND,成功拉取消息的分支会走的流程如下:

首先更新nextOffset对象为pullResult的下次拉取的值,因为后面会将PullRequest对象提交的任务队列里,如果不更新下次拉取的还是同样的内容

② 如果未查询到消息,即CHECK:pullStatus==NO_NEW_MSG…等,则会走如下逻辑:

③ 第三种情况是超出了区间,可以发现并没有将pullRequest对象提交的任务队列中,这样就不会去消费了,下次负载均衡的时候该队列会重新分配再次创建PullRequest对象,会将其放入任务队列

2.4 PullResult对象

PullResult对象的具体内容如下:

在这里插入图片描述
接下来继续看PullAPIWrapper类的核心结构。

3 PullAPIWrapper

该类里面最重要的就是pullFromWhichNodeTable,会根据服务器推荐给当前消费者的下一次拉取的主机去决定下一次去哪个主机上拉(按照队列去推荐),因为消费者的消费进度有可能和当前队列的进度持平,数据全部在内存里面,服务器会建议下次去主节点去拿数据(因为生产者肯定是先将数据写到主节点上的,主节点的热数据都在内存里,从内存里直接查消息效率会非常高),也有可能消费的速度非常慢导致需要去到服务器上去拿冷数据,如果要拿冷数据,服务器需要推荐其去备份broker节点拿冷数据。

在这里插入图片描述

拉消息的核心方法是pullKernellImpl方法,具体实现如下:因为offset在主节点上保存,从节点不需要,因此从节点的sysFalg该位为0。offsetStore在客户端实例里面的定时任务每五秒触发一次持久化消费者进度,调用consumer的持久化方法,最终会调用consumer的OffsetStore的persistAll方法,该方法会遍历在offsetStore表中的消费进度到broker节点,正产情况下拿到的是主节点debroker对象(里面有根据brokerName获取的brokerAddrTable的HashMap,key为Long类型,遍历该HashMap,由于主节点的Key的Hash值是在从节点前面,因此遍历先拿到的正常情况为主节点------->因为Long类型的Hash值的获取方式就是获取当前值)
在这里插入图片描述

该方法的核心参数如下:

  1. messageQueue(包含:主题、broker、 queueld)
  2. nextOffset (本次拉消息的开始offset)
  3. pullBatchSize 默认值为32 (DefaultMQPushConsumer 内的字段)
  4. sysFlag (前面说过了…)
  5. commitOffsetValue(消费者消费进度)
  6. brokerSuspendMaxTimeMillis (Broker端长轮询时, 最大Hold时间,默认: 15秒)
  7. pullCallback ( 上一步创建的)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值