废话
这篇文章主要讲RocketMQ的长轮询,为什么叫长轮询我也不清楚….主要别人这样叫我也这样叫吧,大家明白意思就好。
正文
RcocketMQ消费者的模式是pull模式,也就是会定时向Broker请求消息进行消费。在源码中实现是开启了后台线程不停的去pull(当然会先从队列去PullRequest,队列为空会阻塞),刚研究RocketMQ消费者pull的代码之后不久,有个问题:
- 如果长时间没有消息,消费者不停的去请求那不就会导致broker负载很高吗
当时没有想太多这个问题,后来才发现的,那么我们先回顾一下Broker在没有消息的时候是怎么处理的,首先当然是先获取消息了(下面代码在PullMessageProcessor.java中)
// ....省略其他代码
final GetMessageResult getMessageResult =
this.brokerController.getMessageStore().getMessage(requestHeader.getConsumerGroup(), requestHeader.getTopic(),
requestHeader.getQueueId(), requestHeader.getQueueOffset(), requestHeader.getMaxMsgNums(), subscriptionData);
// ....省略其他代码
然后看下对Result的判断
switch (getMessageResult.getStatus()) {
// ....省略其他代码
case NO_MATCHED_LOGIC_QUEUE:
case NO_MESSAGE_IN_QUEUE:
if (0 != requestHeader.getQueueOffset()) {
// ....省略其他代码
} else {
response.setCode(ResponseCode.PULL_NOT_FOUND);
}
break;
case OFFSET_FOUND_NULL:
response.setCode(ResponseCode.PULL_NOT_FOUND);
break;
case OFFSET_OVERFLOW_ONE:
response.setCode(ResponseCode.PULL_NOT_FOUND);
break;
}
上面是没有找到消息的情况,response是要相应给消费者的,这是为特定的code。
下面看下对response的code的判断
switch (response.getCode()) {
case ResponseCode.PULL_NOT_FOUND:
if (brokerAllowSuspend && hasSuspendFlag) {
// 如果broker开启了长轮询,则将长轮询时间设置为30s(消费者传过来的,默认30s),否则设置为1s
long pollingTimeMills = suspendTimeoutMillisLong;