疑问:PullRequest何时添加?

PullMessageService提供延迟添加与立即添加2种方式

疑问:PullRequest是在什么时候创建的呢?

1.上上图中 PullRequest pullRequest = this.pullRequestQueue.take(); this.pullMessage(pullRequest);mq根据PullRequest拉取任务执行完一次消息拉取任务之后,又将PullRequest对象放入到pullRequestQueue,第二个是在RebalancceImpl中创建。

PullMessageService只有在拿到PullRequest对象时才会执行拉取任务,看一下PullRequest的属性:

看下this.pullMessage的实现:

ProcessQueue实现机制:

ProcessQueue是MessageQueue在消费端的重现,快照。PullMessageService从消息服务器默认每次拉取32条消息,按消息的队列偏移量顺序存放在ProcessQueue中,PullMessageService之后将消息提交到消费者消费线程池,消息成功消费后从ProcessQueue中移除。

消息拉取基本流程

1.消息拉取客户端 消息拉取请求封装

2.消息服务器查找并返回消息

3.消息拉取客户端处理返回的消息

入口:DefaultMQPushConsumerImpl#pullMessage.

队列被丢弃,消费者被挂起,将拉取任务延迟1s再次放入到拉取任务队列中。

消息拉取流控,从消息消费数量与消费间隔两个维度进行控制。

顺序消息没有拿到锁不能进行消费

拉取该主题订阅信息,如果为空,结束本次消息拉取,关于该队列的下一次拉取任务延迟3s。

构建消息拉取系统标记:

调用pullAPIWrapper.pullKernelImpl方法与服务端交互,调用pullKernelImpl方法之前先了解一下其参数含义。

mq:从哪个消息消费队列拉取消息。

subExpression:消息过滤表达式。

expressionType:消息表达式类型

offset:消息拉取偏移量

maxNums:本次拉取最大消息条数,默认32条

sysFlag:拉取系统标记

commitOffset:当前MessageQueue的消费进度(内存中)

brokerSuspendMaxTimeMillis:消息拉取过程中允许Broker挂起时间。默认15秒

timeoutMills:消息拉取超时时间。

communicationMode:消息拉取模式,默认为异步拉取

pullCallback:从Broker拉取到消息后的回调方法。

根据brokerName,BrokerId从MQClientInstance中获取Broker地址,在整个MQ Broker的部署结构中,相同名称的Broker构成主从结构,其BrokerId会不一样,在每次拉取消息后,会给出一个建议,下次拉取从主节点还是从节点拉取。

如果消息过滤模式为类过滤,则需要根据主题名称,broker地址找到注册在Broker上的FilterServer地址,从FilterServer上拉取消息,否则从Broker上拉取消息。

根据RequestCode.PULL_MESSAGE找到Broker端处理消息拉取的入口:

PullMessageProcessor#processRequest:

1.根据订阅信息,构建消息过滤器。

2.调用MessageStore.getMessage查找消息:

根据主题名称与队列编号获取消息消费队列。 

消息偏移量异常情况下校对下一次拉取偏移量

根据消息队列偏移量从commitlog文件中查找消息。

根据PullResult填充ResponseHeader的nextBegainOffset,minOffset,maxOffset。

根据主从同步延迟,如果从节点数据包含下一次拉取的偏移量,设置下一次拉取任务的brokerId:

根据GetMessageResult编码转化成response。

如果commitlog标记可用并且当前节点为主节点,则更新消息消费进度。

最后整理一下返回结果的枚举:

在getMessgae之前的校验逻辑会返回下面这些code:

在getMessage之后会拿到getMessageStatus:

最后一getMessageStatus会转化成:

当最后的response返回给客户端的时候客户端是这么处理的:

下面内容详情见:https://www.cnblogs.com/lccsblog/p/12249265.html

同步消费:

除了下面几种其他直接抛出了异常:

异步消费:

也是先进行上面的过程,然后进行了回调:

最后再看下消息拉去之后的回调:

再看下callback:

可以看到除了FOUND之外NO_MATCHED_MSG和NO_NEW_MSG都会进行重试,OFFSET_ILLEGAL则drop了消费队列,继续看下FOUND:

下面内容,详情见:https://www.cnblogs.com/lccsblog/p/12262334.html

最终会回调我们创建consumer的时候注册的listener。

看下我们在listener中的返回会影响什么:

先是兼容了返回为空和超时的情况。

看下最后的processConsumeResult:

【mq读书笔记】消息拉取的更多相关文章

  1. 【mq读书笔记】消息拉取长轮训机制(Broker端)

    RocketMQ并没有真正实现推模式,而是消费者主动想消息服务器拉取消息,推模式是循环向消息服务端发送消息拉取请求. 如果消息消费者向RocketMQ发送消息拉取时,消息未到达消费队列: 如果不启用长 ...

  2. 【mq读书笔记】顺序消息

    注意异常情况导致整个消费无限重试 阻塞消费 mq支持局部消息顺序消费,可以确保同一个消息消费队列中的消息被顺序消费.看下针对顺序消息在整个消费过程中做的调整: 队列负载: DefaultMQPushC ...

  3. 【mq读书笔记】消息过滤机制

    mq支持表达式过滤和类过滤两种模式,其中表达式又分为TAG和SQL92.类过滤模式允许提交一个过滤类到FilterServer,消息消费者从FilterServer拉取消息,消息经过FilterSer ...

  4. 【mq读书笔记】消息确认(失败消息,定时队列重新消费)

    接上文的集群模式,监听器返回RECONSUME_LATER,需要将将这些消息发送给Broker延迟消息.如果发送ack消息失败,将延迟5s后提交线程池进行消费. 入口:ConsumeMessageCo ...

  5. 【mq读书笔记】消息消费过程(钩子 失败重试 消费偏移记录)

    在https://www.cnblogs.com/lccsblog/p/12249265.html中,PullMessageService负责对消息队列进行消息拉取,从远端服务器拉取消息后将消息存入P ...

  6. 【mq读书笔记】mq消息消费

    消息消费以组的的模式开展: 一个消费组内可以包含多个消费者,每一个消费组可订阅多个主题: 消费组之间有集群模式与广播模式两种消费模式:集群模式-主题下的同一条消息只允许被其中一个消费者消费.广播模式- ...

  7. 【mq读书笔记】消息到达唤醒挂起线程检查新消息

    DefaultMessageStore#start 当新消息到达CommitLog是,ReputMessageService线程负责将消息转发给ConsumeQueue,IndexFile,如果Bro ...

  8. 【mq读书笔记】客户端处理消息(回调提交到异步业务线程池,pullRequest重新入队)

    看一下客户端收到消息后的处理: MQClientAPIImpl#processPullResponse private PullResult processPullResponse( final Re ...

  9. RocketMQ中PullConsumer的消息拉取源码分析

    在PullConsumer中,有关消息的拉取RocketMQ提供了很多API,但总的来说分为两种,同步消息拉取和异步消息拉取 同步消息拉取以同步方式拉取消息都是通过DefaultMQPullConsu ...

随机推荐

  1. “wget: 无法解析主机地址”的解决方法

    问题: 1 [root@iZ2zefny2a19ms6azli2pwZ ~]# wget https://download.redis.io/releases/redis-5.0.10.tar.gz ...

  2. Linux 网络编程的5种IO模型:多路复用(select/poll/epoll)

    Linux 网络编程的5种IO模型:多路复用(select/poll/epoll) 背景 我们在上一讲 Linux 网络编程的5种IO模型:阻塞IO与非阻塞IO中,对于其中的 阻塞/非阻塞IO 进行了 ...

  3. 如何对List集合中的对象进行按某个属性排序

    我们在实际的开发工作中,经常会碰到排序的问题,如题,我们如何针对List集合中的某一个属性进行排序 当list集合中的元素类型是我们自定义类型时,有两种对list中的元素进行排序的方法: 方法一 让l ...

  4. C#循环判断密码

      要求用户输入用户名和密码,只要不是admin.888888就一直提示用户名或密码错误,请重新输入 while (true) { Console.WriteLine("请输入帐号和密码&q ...

  5. JavaSE基础语法学习

    标识符 表示类名的标识符用大写字母开始. 表示方法和变量的标识符用小写字母开始,后面的描述性词以大写开始. 注意 所有的标识符都应该以字母(A-Z 或者 a-z),美元符($).或者下划线(_)开始 ...

  6. Hopfield Network 霍普菲尔德网络入门

    简介 Hopfield Network (霍普菲尔德网络),是 Hopfield 在1982年提出的一种基于能量的模型,发表的文章是 Neural networks and physical syst ...

  7. 3. Spark常见数据源

    *以下内容由<Spark快速大数据分析>整理所得. 读书笔记的第三部分是讲的是Spark有哪些常见数据源?怎么读取它们的数据并保存. Spark有三类常见的数据源: 文件格式与文件系统:它 ...

  8. [MIT6.006] 12. Square Roots, Newton's Method 平方根,牛顿法

    首先让我们回顾下上节课讲的,用牛顿法计算√2的内容: 简单来说,牛顿法从x0=1不断向后计算逼近√2的值,而刚开始计算的精度是1,随着牛顿法的逼近(共log2d个循环),就能使得√2逼近值的精度达到d ...

  9. nginx&http 第五章 https non-fd 读写检测

    EPOLL的LT/ET 模式下的读写 从一个非阻塞的socket上调用recv/send函数, 返回EAGAIN或者EWOULDBLOCK(注: EAGAIN就是EWOULDBLOCK)从字面上看, ...

  10. nginx&http 第三章 ngx http ngx_http_process_request_headers

    HTTP 请求行正确处理完成后,针对 HTTP/1.0 及以上版本紧接着要做的就是请求 HEADER 的处理与解析了 /** * 用于处理http的header数据 * 请求头: * Host: lo ...