概述
Consumer 通过 PullMessageService 线程拉取消息。PullMessageService 从 pullRequestQueue 获取 拉取消息请求(PullRequest), 从而向 Broker 拉取消息。
消息拉取消息后,会把消息放入本地的 ProcessQueue. 再由消费者消费 ProcessQueue 中的数据。
消息拉取流程
流程图解
消息拉取
代码位置: DefaultMQPushConsumerImpl#pullMessage()
-
Rebalance结束后,会往PullMessageService的pullRequestQueue中添加一个PullRequest -
PullMessageService从队列中取出 1 个PullRequest,然后向Broker拉取 32 条消息(默认)。Consumer可通过pullBatchSize参数控制。 -
如果
Consumer的ProcessQueue消息大于 1000 条 或者ProcessQueue堆积的消息大小超过 100MB, 会触发流控,即延迟50ms再拉取消息。否则拉取一次消息,会立马又发生请求拉取消息。
Consumer 可通过调用 setPullThresholdForQueue(), setPullThresholdSizeForQueue()。设置触发流控阈值.
提醒
ProcessQueue是以消费者组为单位的。
broker 端处理消息拉取
代码位置: PullMessageProcessor#processRequest()
-
Broker先从ConsumerQueue中根据拉取偏移量,拉取消息 -
如果消费者有根据 tag 过滤消息,则根据
ConsumerQueue Item的tagHashCode快速过滤消息 -
根据
ConsumerQueue Item的offset从CommitLog中拉取消息 -
如果消费者消费太慢。 则建议
Consumer下次拉取消息时,从slave拉取消息。消费太慢的判断依据是 (当前CommitLog的最大偏移量 - 拉取消息的最大偏移量) / 机器物理内存 > 40% -
返回数据给消费端
Consumer 处理拉取到的消息
-
Consumer本地再次过滤消息。 -
如果是 tag 过滤,则比较
tag hashcode的值。 -
过滤完消息后将 消息放入本地的
ProcessQueue。 -
再往
pullRequestQueue中存放PullRequest, 准备下次拉取。
总结
-
默认用的
Push模式拉消息.Push是用Pull实现的, 即长轮询。 -
消息拉取时,
Consumer端有流控;默认的行为是:ProcessQueue的消息数量超过1000条,或者消息大小超过100MB则延迟50ms拉消息。 -
消息过滤时,如果是
tag,Broker端会先按照tag hashcode进行粗粒度的过滤;最后Consumer端再根据tag的值进行过滤。 -
拉取到消息后,并不是直接消费,而是放入本地的
ProcessQueue, 供后续的消费者线程去消费。