rocketmq源码解析之管理请求查询消费队列

说在前面

管理请求之查询消费队列

 

源码解析

进入这个方法,org.apache.rocketmq.broker.processor.AdminBrokerProcessor#queryConsumeQueue

private RemotingCommand queryConsumeQueue(ChannelHandlerContext ctx,        RemotingCommand request) throws RemotingCommandException {        QueryConsumeQueueRequestHeader requestHeader =            (QueryConsumeQueueRequestHeader) request.decodeCommandCustomHeader(QueryConsumeQueueRequestHeader.class);
        RemotingCommand response = RemotingCommand.createResponseCommand(null);
//        获取消费队列=》        ConsumeQueue consumeQueue = this.brokerController.getMessageStore().getConsumeQueue(requestHeader.getTopic(),            requestHeader.getQueueId());        if (consumeQueue == null) {            response.setCode(ResponseCode.SYSTEM_ERROR);            response.setRemark(String.format("%d@%s is not exist!", requestHeader.getQueueId(), requestHeader.getTopic()));            return response;        }
        QueryConsumeQueueResponseBody body = new QueryConsumeQueueResponseBody();        response.setCode(ResponseCode.SUCCESS);        response.setBody(body.encode());
        body.setMaxQueueIndex(consumeQueue.getMaxOffsetInQueue());        body.setMinQueueIndex(consumeQueue.getMinOffsetInQueue());
        MessageFilter messageFilter = null;        if (requestHeader.getConsumerGroup() != null) {//            按消费组、topic查询订阅信息=》            SubscriptionData subscriptionData = this.brokerController.getConsumerManager().findSubscriptionData(                requestHeader.getConsumerGroup(), requestHeader.getTopic()            );            body.setSubscriptionData(subscriptionData);            if (subscriptionData == null) {                body.setFilterData(String.format("%s@%s is not online!", requestHeader.getConsumerGroup(), requestHeader.getTopic()));            } else {//                获取消费者过滤信息=》                ConsumerFilterData filterData = this.brokerController.getConsumerFilterManager()                    .get(requestHeader.getTopic(), requestHeader.getConsumerGroup());                body.setFilterData(JSON.toJSONString(filterData, true));
                messageFilter = new ExpressionMessageFilter(subscriptionData, filterData,                    this.brokerController.getConsumerFilterManager());            }        }
//        根据index获取selectMappedBufferResult=》        SelectMappedBufferResult result = consumeQueue.getIndexBuffer(requestHeader.getIndex());        if (result == null) {            response.setRemark(String.format("Index %d of %d@%s is not exist!", requestHeader.getIndex(), requestHeader.getQueueId(), requestHeader.getTopic()));            return response;        }        try {            List<ConsumeQueueData> queues = new ArrayList<>();            for (int i = 0; i < result.getSize() && i < requestHeader.getCount() * ConsumeQueue.CQ_STORE_UNIT_SIZE; i += ConsumeQueue.CQ_STORE_UNIT_SIZE) {                ConsumeQueueData one = new ConsumeQueueData();                one.setPhysicOffset(result.getByteBuffer().getLong());                one.setPhysicSize(result.getByteBuffer().getInt());                one.setTagsCode(result.getByteBuffer().getLong());
                if (!consumeQueue.isExtAddr(one.getTagsCode())) {                    queues.add(one);                    continue;                }
                ConsumeQueueExt.CqExtUnit cqExtUnit = consumeQueue.getExt(one.getTagsCode());                if (cqExtUnit != null) {                    one.setExtendDataJson(JSON.toJSONString(cqExtUnit));                    if (cqExtUnit.getFilterBitMap() != null) {                        one.setBitMap(BitsArray.create(cqExtUnit.getFilterBitMap()).toString());                    }                    if (messageFilter != null) {                        one.setEval(messageFilter.isMatchedByConsumeQueue(cqExtUnit.getTagsCode(), cqExtUnit));                    }                } else {                    one.setMsg("Cq extend not exist!addr: " + one.getTagsCode());                }
                queues.add(one);            }            body.setQueueData(queues);        } finally {            result.release();        }
        return response;    }

进入这个方法, 获取消费队列,org.apache.rocketmq.store.DefaultMessageStore#getConsumeQueue

@Override    public ConsumeQueue getConsumeQueue(String topic, int queueId) {        ConcurrentMap<Integer, ConsumeQueue> map = consumeQueueTable.get(topic);        if (map == null) {            return null;        }        return map.get(queueId);    }

往上返回到这个方法,按消费组、topic查询订阅信息,org.apache.rocketmq.broker.client.ConsumerManager#findSubscriptionData

 public SubscriptionData findSubscriptionData(final String group, final String topic) {//        按组从缓存中获取消费组信息        ConsumerGroupInfo consumerGroupInfo = this.getConsumerGroupInfo(group);        if (consumerGroupInfo != null) {//            按topic从缓存中获取订阅数据            return consumerGroupInfo.findSubscriptionData(topic);        }
        return null;    }

往上返回到这个方法,获取消费者过滤信息,org.apache.rocketmq.broker.filter.ConsumerFilterManager#get(java.lang.String, java.lang.String)

public ConsumerFilterData get(final String topic, final String consumerGroup) {        if (!this.filterDataByTopic.containsKey(topic)) {            return null;        }        if (this.filterDataByTopic.get(topic).getGroupFilterData().isEmpty()) {            return null;        }
        return this.filterDataByTopic.get(topic).getGroupFilterData().get(consumerGroup);    }

往上返回到这个方法,根据index获取selectMappedBufferResult,org.apache.rocketmq.store.ConsumeQueue#getIndexBuffer

public SelectMappedBufferResult getIndexBuffer(final long startIndex) {        int mappedFileSize = this.mappedFileSize;//        获取最小的物理offset        long offset = startIndex * CQ_STORE_UNIT_SIZE;        if (offset >= this.getMinLogicOffset()) {//            根据offset查询映射文件 =》            MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);            if (mappedFile != null) {                SelectMappedBufferResult result = mappedFile.selectMappedBuffer((int) (offset % mappedFileSize));                return result;            }        }        return null;    }

进入这个方法, 根据offset查询映射文件,org.apache.rocketmq.store.MappedFileQueue#findMappedFileByOffset(long)

public MappedFile findMappedFileByOffset(final long offset) {//        =》        return findMappedFileByOffset(offset, false);    }

进入这个方法,org.apache.rocketmq.store.MappedFileQueue#findMappedFileByOffset(long, boolean)

public MappedFile findMappedFileByOffset(final long offset, final boolean returnFirstOnNotFound) {        try {//            获取队列中第一个映射文件            MappedFile firstMappedFile = this.getFirstMappedFile();//            获取队列中最后一个映射文件            MappedFile lastMappedFile = this.getLastMappedFile();            if (firstMappedFile != null && lastMappedFile != null) {//                如果offset不在索引文件的offset范围内                if (offset < firstMappedFile.getFileFromOffset() || offset >= lastMappedFile.getFileFromOffset() + this.mappedFileSize) {                    LOG_ERROR.warn("Offset not matched. Request offset: {}, firstOffset: {}, lastOffset: {}, mappedFileSize: {}, mappedFiles count: {}",                        offset,                        firstMappedFile.getFileFromOffset(),                        lastMappedFile.getFileFromOffset() + this.mappedFileSize,                        this.mappedFileSize,                        this.mappedFiles.size());                } else {//                   找到映射文件在队列中的索引位置                    int index = (int) ((offset / this.mappedFileSize) - (firstMappedFile.getFileFromOffset() / this.mappedFileSize));                    MappedFile targetFile = null;                    try {//                        获取索引文件                        targetFile = this.mappedFiles.get(index);                    } catch (Exception ignored) {                    }
//                    offset在目标文件的起始offset和结束offset范围内                    if (targetFile != null && offset >= targetFile.getFileFromOffset()                        && offset < targetFile.getFileFromOffset() + this.mappedFileSize) {                        return targetFile;                    }
//                    如果按索引在队列中找不到映射文件就遍历队列查找映射文件                    for (MappedFile tmpMappedFile : this.mappedFiles) {                        if (offset >= tmpMappedFile.getFileFromOffset()                            && offset < tmpMappedFile.getFileFromOffset() + this.mappedFileSize) {                            return tmpMappedFile;                        }                    }                }
//                如果offset=0获取队列中第一个映射文件,个人感觉这个逻辑是否放在前面判断更为合理,还是放在这里另有深意                if (returnFirstOnNotFound) {                    return firstMappedFile;                }            }        } catch (Exception e) {            log.error("findMappedFileByOffset Exception", e);        }
        return null;    }

往上返回到这个方法org.apache.rocketmq.broker.processor.AdminBrokerProcessor#queryConsumeQueue结束。

 

说在最后

本次解析仅代表个人观点,仅供参考。

 

加入技术微信群

钉钉技术群

转载于:https://my.oschina.net/u/3775437/blog/3094977

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值