response.setRemark("the consumer's subscription not latest");
return response;
}
}
final GetMessageResult getMessageResult =
this.brokerController.getMessageStore().getMessage(requestHeader.getTopic(),
requestHeader.getQueueId(), requestHeader.getQueueOffset(),
requestHeader.getMaxMsgNums(), subscriptionData);
if (getMessageResult != null) {
response.setRemark(getMessageResult.getStatus().name());
responseHeader.setNextBeginOffset(getMessageResult.getNextBeginOffset());
responseHeader.setMinOffset(getMessageResult.getMinOffset());
responseHeader.setMaxOffset(getMessageResult.getMaxOffset());
// 消费较慢,重定向到另外一台机器
if (getMessageResult.isSuggestPullingFromSlave()) {
responseHeader.setSuggestWhichBrokerId(subscriptionGroupConfig
.getWhichBrokerWhenConsumeSlowly());
}
// 消费正常,按照订阅组配置重定向
else {
responseHeader.setSuggestWhichBrokerId(subscriptionGroupConfig.getBrokerId());
}
switch (getMessageResult.getStatus()) {
case FOUND:
response.setCode(ResponseCode.SUCCESS);
// 消息轨迹:记录客户端拉取的消息记录(不表示消费成功)
if (this.hasConsumeMessageHook()) {
// 执行hook
ConsumeMessageContext context = new ConsumeMessageContext();
context.setConsumerGroup(requestHeader.getConsumerGroup());
context.setTopic(requestHeader.getTopic());
context.setClientHost(RemotingHelper.parseChannelRemoteAddr(channel));
context.setStoreHost(this.brokerController.getBrokerAddr());
context.setQueueId(requestHeader.getQueueId());
final SocketAddress storeHost =
new InetSocketAddress(brokerController.getBrokerConfig().getBrokerIP1(),
brokerController.getNettyServerConfig().getListenPort());
Map<String, Long> messageIds =
this.brokerController.getMessageStore().getMessageIds(requestHeader.getTopic(),
requestHeader.getQueueId(), requestHeader.getQueueOffset(),
requestHeader.getQueueOffset() + getMessageResult.getMessageCount(),
storeHost);
context.setMessageIds(messageIds);
context.setBodyLength(getMessageResult.getBufferTotalSize()
/ getMessageResult.getMessageCount());
this.executeConsumeMessageHookBefore(context);
}
break;
case MESSAGE_WAS_REMOVING:
response.setCode(ResponseCode.PULL_RETRY_IMMEDIATELY);
break;
// 这两个返回值都表示服务器暂时没有这个队列,应该立刻将客户端Offset重置为0
case NO_MATCHED_LOGIC_QUEUE:
case NO_MESSAGE_IN_QUEUE:
if (0 != requestHeader.getQueueOffset()) {
response.setCode(ResponseCode.PULL_OFFSET_MOVED);
// XXX: warn and notify me
log.info(
"the broker store no queue data, fix the request offset {} to {}, Topic: {} QueueId: {} Consumer Group: {}",//
requestHeader.getQueueOffset(), //
getMessageResult.getNextBeginOffset(), //
requestHeader.getTopic(),//
requestHeader.getQueueId(),//
requestHeader.getConsumerGroup()//
);
}
else {
response.setCode(ResponseCode.PULL_NOT_FOUND);
}
break;
case NO_MATCHED_MESSAGE:
response.setCode(ResponseCode.PULL_RETRY_IMMEDIATELY);
break;
case OFFSET_FOUND_NULL:
response.setCode(ResponseCode.PULL_NOT_FOUND);
break;
case OFFSET_OVERFLOW_BADLY:
response.setCode(ResponseCode.PULL_OFFSET_MOVED);
// XXX: warn and notify me
log.info("the request offset: " + requestHeader.getQueueOffset()
+ " over flow badly, broker max offset: " + getMessageResult.getMaxOffset()
+ ", consumer: " + channel.remoteAddress());
break;
case OFFSET_OVERFLOW_ONE:
response.setCode(ResponseCode.PULL_NOT_FOUND);
break;
case OFFSET_TOO_SMALL:
response.setCode(ResponseCode.PULL_OFFSET_MOVED);
// XXX: warn and notify me
log.info("the request offset: " + requestHeader.getQueueOffset()
+ " too small, broker min offset: " + getMessageResult.getMinOffset()
+ ", consumer: " + channel.remoteAddress());
break;
default:
assert false;
break;
}
switch (response.getCode()) {
case ResponseCode.SUCCESS:
// 统计
this.brokerController.getBrokerStatsManager().incGroupGetNums(
requestHeader.getConsumerGroup(), requestHeader.getTopic(),
getMessageResult.getMessageCount());
this.brokerController.getBrokerStatsManager().incGroupGetSize(
requestHeader.getConsumerGroup(), requestHeader.getTopic(),
getMessageResult.getBufferTotalSize());
this.brokerController.getBrokerStatsManager().incBrokerGetNums(
getMessageResult.getMessageCount());
try {
FileRegion fileRegion =
new ManyMessageTransfer(response.encodeHeader(getMessageResult
.getBufferTotalSize()), getMessageResult);
channel.writeAndFlush(fileRegion).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
getMessageResult.release();
if (!future.isSuccess()) {
log.error(
"transfer many message by pagecache failed, " + channel.remoteAddress(),
future.cause());
}
}
});
}
catch (Throwable e) {
log.error("", e);
getMessageResult.release();
}
response = null;
break;
case ResponseCode.PULL_NOT_FOUND:
// 长轮询
if (brokerAllowSuspend && hasSuspendFlag) {
PullRequest pullRequest =
new PullRequest(request, channel, suspendTimeoutMillisLong, this.brokerController
.getMessageStore().now(), requestHeader.getQueueOffset());
this.brokerController.getPullRequestHoldService().suspendPullRequest(
requestHeader.getTopic(), requestHeader.getQueueId(), pullRequest);
response = null;
break;
}
// 向Consumer返回应答
case ResponseCode.PULL_RETRY_IMMEDIATELY:
break;
case ResponseCode.PULL_OFFSET_MOVED:
MessageQueue mq = new MessageQueue();
mq.setTopic(requestHeader.getTopic());
mq.setQueueId(requestHeader.getQueueId());
mq.setBrokerName(this.brokerController.getBrokerConfig().getBrokerName());
OffsetMovedEvent event = new OffsetMovedEvent();
event.setConsumerGroup(requestHeader.getConsumerGroup());
event.setMessageQueue(mq);
event.setOffsetRequest(requestHeader.getQueueOffset());
event.setOffsetNew(getMessageResult.getNextBeginOffset());
this.generateOffsetMovedEvent(event);
break;
default:
assert false;
}