RocketMQ中PullConsumer的消息拉取源码分析,
在PullConsumer中,有关消息的拉取RocketMQ提供了很多API,但总的来说分为两种,同步消息拉取和异步消息拉取
同步消息拉取
以同步方式拉取消息都是通过DefaultMQPullConsumerImpl的pullSyncImpl方法:
1 private PullResult pullSyncImpl(MessageQueue mq, SubscriptionData subscriptionData, long offset, int maxNums, booleanblock,2 longtimeout)3 throwsMQClientException, RemotingException, MQBrokerException, InterruptedException {4 this.makeSureStateOK();5
6 if (null ==mq) {7 throw new MQClientException("mq is null", null);8 }9
10 if (offset < 0) {11 throw new MQClientException("offset < 0", null);12 }13
14 if (maxNums <= 0) {15 throw new MQClientException("maxNums <= 0", null);16 }17
18 this.subscriptionAutomatically(mq.getTopic());19
20 int sysFlag = PullSysFlag.buildSysFlag(false, block, true, false);21
22 long timeoutMillis = block ? this.defaultMQPullConsumer.getConsumerTimeoutMillisWhenSuspend() : timeout;23
24 boolean isTagType =ExpressionType.isTagType(subscriptionData.getExpressionType());25 PullResult pullResult = this.pullAPIWrapper.pullKernelImpl(26 mq,27 subscriptionData.getSubString(),28 subscriptionData.getExpressionType(),29 isTagType ? 0L: subscriptionData.getSubVersion(),30 offset,31 maxNums,32 sysFlag,33 0,34 this.defaultMQPullConsumer.getBrokerSuspendMaxTimeMillis(),35 timeoutMillis,36 CommunicationMode.SYNC,37 null
38 );39 this.pullAPIWrapper.processPullResult(mq, pullResult, subscriptionData);40 if (!this.consumeMessageHookList.isEmpty()) {41 ConsumeMessageContext consumeMessageContext = null;42 consumeMessageContext = newConsumeMessageContext();43 consumeMessageContext.setConsumerGroup(this.groupName());44 consumeMessageContext.setMq(mq);45 consumeMessageContext.setMsgList(pullResult.getMsgFoundList());46 consumeMessageContext.setSuccess(false);47 this.executeHookBefore(consumeMessageContext);48 consumeMessageContext.setStatus(ConsumeConcurrentlyStatus.CONSUME_SUCCESS.toString());49 consumeMessageContext.setSuccess(true);50 this.executeHookAfter(consumeMessageContext);51 }52 returnpullResult;53 }
首先通过subscriptionAutomatically方法检查Topic是否订阅
1 public void subscriptionAutomatically(finalString topic) {2 if (!this.rebalanceImpl.getSubscriptionInner().containsKey(topic)) {3 try{4 SubscriptionData subscriptionData = FilterAPI.buildSubscriptionData(this.defaultMQPullConsumer.getConsumerGroup(),5 topic, SubscriptionData.SUB_ALL);6 this.rebalanceImpl.subscriptionInner.putIfAbsent(topic, subscriptionData);7 } catch(Exception ignore) {8 }9 }10 }
若是没有就新建一条订阅数据保存在rebalanceImpl的subscriptionInner中
之后调用pullKernelImpl方法:
1 publicPullResult pullKernelImpl(2 finalMessageQueue mq,3 finalString subExpression,4 finalString expressionType,5 final longsubVersion,6 final longoffset,7 final intmaxNums,8 final intsysFlag,9 final longcommitOffset,10 final longbrokerSuspendMaxTimeMillis,11 final longtimeoutMillis,12 finalCommunicationMode communicationMode,13 finalPullCallback pullCallback14 ) throwsMQClientException, RemotingException, MQBrokerException, InterruptedException {15 FindBrokerResult findBrokerResult =
16 this.mQClientFactory.findBrokerAddressInSubscribe(mq.getBrokerName(),17 this.recalculatePullFromWhichNode(mq), false);18 if (null ==findBrokerResult) {19 this.mQClientFactory.updateTopicRouteInfoFromNameServer(mq.getTopic());20 findBrokerResult =
21 this.mQClientFactory.findBrokerAddressInSubscribe(mq.getBrokerName(),22 this.recalculatePullFromWhichNode(mq), false);23 }24
25 if (findBrokerResult != null) {26 {27 //check version
28 if (!ExpressionType.isTag