概述
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
, 供后续的消费者线程去消费。