1. DefaultMQPullConsumerImpl
通过pullSyncImpl(MessageQueue mq, SubscriptionData subscriptionData, long offset, int maxNums, boolean block, long timeout)来拉取消息。
通过 pullAPIWrapper 该类的方法对broker发起请求
PullResult pullResult = this.pullAPIWrapper.pullKernelImpl(
mq,
subscriptionData.getSubString(),
subscriptionData.getExpressionType(),
isTagType ? 0L : subscriptionData.getSubVersion(),
offset,
maxNums,
sysFlag,
0,
this.defaultMQPullConsumer.getBrokerSuspendMaxTimeMillis(),
timeoutMillis,
CommunicationMode.SYNC,
null
);
在 pullKernelImpl的方法中, 封装了消息所在队列,消费偏移量,主题的信息,保存在请求头中。
PullMessageRequestHeader requestHeader = new PullMessageRequestHeader(); requestHeader.setConsumerGroup(this.consumerGroup);
requestHeader.setTopic(mq.getTopic());
requestHeader.setQueueId(mq.getQueueId());
requestHeader.setQueueOffset(offset);
requestHeader.setMaxMsgNums(maxNums);
requestHeader.setSysFlag(sysFlagInner);
requestHeader.setCommitOffset(commitOffset);
requestHeader.setSuspendTimeoutMillis(brokerSuspendMaxTimeMillis);
requestHeader.setSubscription(subExpression);
requestHeader.setSubVersion(subVersion);
requestHeader.setExpressionType(expressionType);
通过pullMessage() 方法进行拉取请求, 拉取请求可以分为同步,异步的模式。 异步模式,会在拉取完成之后执行回调函数。
PullResult pullResult = this.mQClientFactory.getMQClientAPIImpl().pullMessage(
brokerAddr,
requestHeader,
timeoutMillis,
communicationMode,
pullCallback);
switch (communicationMode) {
case ONEWAY:
assert false;
return null;
case ASYNC:
this.pullMessageAsync(addr, request, timeoutMillis, pullCallback);
return null;
case SYNC:
return this.pullMessageSync(addr, request, timeoutMillis);
default:
assert false;
break;
}
拉取请求主要是通过netty进行网络请求完成的,最后把broker返回结果RemotingCommand转为PullResult
PullResult 的里面包含的信息主要是拉取状态,队列的相关信息和消费消息的位置信息。
public class PullResult {
//拉取结果
private final PullStatus pullStatus;
//下次拉取偏移量
private final long nextBeginOffset;
//消息队列最小偏移量
private final long minOffset;
//消息队列最大偏移量
private final long maxOffset;
//具体拉取的消息列表
private List<MessageExt> msgFoundList;
其中MessageExt里面包含了队列id, 队列的消息偏移量, 存储时间戳,日志文件偏移量, 消息id等信息。
public class MessageExt extends Message {
private static final long serialVersionUID = 5720810158625748049L;
private int queueId;
private int storeSize;
private long queueOffset;
private int sysFlag;
private long bornTimestamp;
private SocketAddress bornHost;
private long storeTimestamp;
private SocketAddress storeHost;
private String msgId;
private long commitLogOffset;
private int bodyCRC;
private int reconsumeTimes;
private long preparedTransactionOffset;
}
其中Message结构包含了具体的消息内容
ublic class Message implements Serializable {
private static final long serialVersionUID = 8445773977080406428L;
//主题信息
private String topic;
//网络通信标记
private int flag;
private Map<String, String> properties;
//具体消息内容
private byte[] body;
//事务消息编号
private String transactionId;
}
用户拉取到消息后, 执行消费代码,即可完成消费。消费进度可以执行updateConsumeOffset()方法,将消费位点上报给Broker, 也可以自行保存消费位点。
@Override
public void updateOffset(MessageQueue mq, long offset, boolean increaseOnly) {
if (mq != null) {
AtomicLong offsetOld = this.offsetTable.get(mq);
if (null == offsetOld) {
offsetOld = this.offsetTable.putIfAbsent(mq, new AtomicLong(offset));
}
if (null != offsetOld) {
if (increaseOnly) {
MixAll.compareAndIncreaseOnly(offsetOld, offset);
} else {
offsetOld.set(offset);
}
}
}
}