RocketMQ的DefaultMQPullConsumerImpl的拉取消息流程分析

本文介绍RocketMQ中DefaultMQPullConsumerImpl组件如何通过不同模式拉取消息,并解析PullResult及MessageExt对象中携带的关键信息,最终实现消息消费。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       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);
                }
            }
        }
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值