RocketMQ消息者PULL请求模式拉取消息

引言

RocketMQ消费者PULL请求模式拉取消息,是通过消费者端与服务端Broker的多个线程进行配合,做到消息拉取的及时与减少拉取的Broker性能损耗(通过长连接)。

  1. 消费者处理发起拉取请求的线程PullMessageService

  2. 服务端Broker处理未拉取到消息的hold线程PullRequestHoldService

  3. 服务端Broker消息写入后的重放后的线程ReputMessageService


 

消费者端 

在消费者启动的过程,在构建MQClientInstance实例的过程中,会创建一个消息拉取线程PullMessageService,并在此启动过程中,开启此线程。

线程中会创建一个大小为0的messageRequestQueue消息请求队列

什么时候会放入messageRequestQueue中呢?

  1. 消费者实例启动中,随着消费者执行负载均衡后,把绑定的消费队列构建成MessageRequest,首次放入到消息请求队列中;

  2. 执行一次消息请求拉取后:

  1. 拉取成功后,会立即再次把当前消息拉取请求MessageRequest放入到消息请求队列中;

  2. 拉取失败或触发流控或者设置的pullInterval不为0,则会通过定时调度在延迟一定时间后,把MessageRequest进行放入到消息请求队列中

// 消息请求队列
private final LinkedBlockingQueue<MessageRequest> messageRequestQueue = new LinkedBlockingQueue<>();
// 定时调度的线程池(主要是执行延迟时间后,把消息请求放入消息请求队列)
private final ScheduledExecutorService scheduledExecutorService = Executors
        .newSingleThreadScheduledExecutor(new ThreadFactoryImpl("PullMessageServiceScheduledThread"));

 消息拉取线程run方法

public void run() {
  // stopped属性(用volatile关键字修饰)默认为false,shutdown时置为true
  while (!this.isStopped()) {
     try {
        // 从消息请求队列中取消息请求
        MessageRequest messageRequest = this.messageRequestQueue.take();
        // POP消息请求模式
        if (messageRequest.getMessageRequestMode() == MessageRequestMode.POP) {
            this.popMessage((PopRequest) messageRequest);
        } else {
            // PULL消息请求模式
            this.pullMessage((PullRequest) messageRequest);
        }
      } catch (InterruptedException ignored) {
      } catch (Exception e) {
         logger.error("Pull Message Service Run Method exception", e);
     }
  }
 }

 pullMessage方法

DefaultMQPushConsumerImpl#pullMessage方法执行逻辑:

1、前置校验

  1. 校验消息处理队列ProcessQueue是否被删除(比如当前消费队列在消费者负载均衡后,不在属于当前消息费实例后,会把这个属性置为删除),若是删除状态,则直接退出;

  2. 校验消费者实例的状态是否为运行中,若不是,则通过定时任务在3s后,再进行消息拉取;

  3. 校验消息者是否被暂停,若是,则通过定时任务在1s后,再进行消息拉取;

  4. 校验是否触发了流控

  1. 当前消息队列对应的消息处理队列中还有1000条,则通过定时任务在50ms后,再进行消息拉取;

  2. 当前消息队列对应的消息处理队列消息大小100M,则通过定时任务执行在50ms后,再进行消息拉取;

  3. 非顺序消费时,当前消息队列对应的消息处理队列消息最大跨度(offset差值)大于200,则通过定时任务在50ms后,再进行消息拉取;

2、 创建拉取消息后的回调处理PullCallback

3、 生成sysFalg标志位

4、构建一次拉取消息请求Broker(默认是异步,一次拉取32条)

  1. 若返回的response不为空,则回调PullCallback进行消费消息,

  2. 若为空,则则通过定时任务执行延迟3000s后,再进行消息拉取;


 

服务端Broker

PullMessageProcessor#processRequest

  1. 校验是否允许消息拉取(如Topic是否存在,订阅关系是否存在等)

  2. 构建一个CompletableFuture,调用PullMessageResultHandler#handle获取拉取的消息结果:

  1. 若拉取消息成功,则把消息体返回给消费者端

  2. 若拉取不到消息,则把消息拉取请求放入到PullRequestHoldService中的pullRequestTable缓存中。

  • PullRequestHoldService是一个处理PullRequest的hold线程,若Broker配置了支持longPollingEnable(默认开启),则会每隔5s处理一次拉取校验(主要是调用notifyMessageArriving,获取是否有新的消息写入),若未支持,则会每隔1s处理一次拉取校验;

  • ReputMessageService消息重放线程,则会每隔1ms处理commitLog中的消息后,也会调用notifyMessageArriving方法进行通知,处理hold的pullRequst,这样可以做到消息到达时的及时返回给消费者端进行消费。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值