Rocketmq面试(六)Rocketmq6种找不到Broker的情况

1.发送消息

Rocketmq Client在发送消息的时候,会根据topic首先从本地缓存获取Broker,获取Broker,如果获取不到,就会到Name Server集群中获取

2.消息偏移量

客户端获取消息偏移量(Consume Offset)的时候,也可能会抛出这个异常:

//RemoteBrokerOffsetStore 类
public long readOffset(final MessageQueue mq, final ReadOffsetType type) {
    if (mq != null) {
        switch (type) {
            case MEMORY_FIRST_THEN_STORE:
            case READ_FROM_MEMORY: {
                //省略实现逻辑
            }
            case READ_FROM_STORE: {
                    //省略
                    long brokerOffset = this.fetchConsumeOffsetFromBroker(mq);
                    //省略
            }
            default:
                break;
        }
    }

    return -1;
}

从上面的代码中可以看到:获取偏移量的方式有 3 种:

  • MEMORY_FIRST_THEN_STORE:先从内存中获取,如果获取不到,再从 Broker 请求;

  • READ_FROM_MEMORY:直接从内存中获取;

  • READ_FROM_STORE:直接从 Broker 请求。

从Broker获取偏移量

private long fetchConsumeOffsetFromBroker(MessageQueue mq) throws RemotingException, MQBrokerException,
InterruptedException, MQClientException {
    FindBrokerResult findBrokerResult = this.mQClientFactory.findBrokerAddressInSubscribe(mq.getBrokerName(), MixAll.MASTER_ID, true);
    if (null == findBrokerResult) {
        this.mQClientFactory.updateTopicRouteInfoFromNameServer(mq.getTopic());
        findBrokerResult = this.mQClientFactory.findBrokerAddressInSubscribe(mq.getBrokerName(), MixAll.MASTER_ID, false);
    }

    if (findBrokerResult != null) {
        //忽略处理逻辑
    } else {
        throw new MQClientException("The broker[" + mq.getBrokerName() + "] not exist", null);
    }
}

这段代码跟上一节发送消息时获取 Broker 地址的代码一样,首先从本地内存中获取,如果过去不到,就从 Name Server 中获取,如果取不到,就抛出 Broker 不存在的异常。

3.获取最早消息的保存时间

public long earliestMsgStoreTime(MessageQueue mq) throws MQClientException {
    String brokerAddr = this.mQClientFactory.findBrokerAddressInPublish(mq.getBrokerName());
    if (null == brokerAddr) {
        this.mQClientFactory.updateTopicRouteInfoFromNameServer(mq.getTopic());
        brokerAddr = this.mQClientFactory.findBrokerAddressInPublish(mq.getBrokerName());
    }
    //省略处理逻辑
    throw new MQClientException("The broker[" + mq.getBrokerName() + "] not exist", null);
}

4.其他获取偏移量方法

除了上面的获取偏移量的方法外,还有 3 个获取偏移量的方法,在 MQAdminImpl 类:

  • searchOffset:从 Broker 获取 Message-Queue 偏移量,跟上面方法类似;

  • maxOffset:从 Broker 获取 MessageQ-ueue 最大偏移量;

  • minOffset:从 Broker 获取 MessageQu-eue 最小偏移量。

5.拉取消息

户端从 Broker 拉取消息之前,首先会从本地缓存获取 Broker 地址,如果获取不到,就从 Name Server 获取 Broker 地址,如果获取失败,则抛出 Broker 不存在的异常。

6.偏移量不合法

如果拉取消息时返回偏移量不合法(OFFSET_ILLEGAL),这时就需要重新处理偏移量。客户端代码的调用关系如下:

这个发生在事务消息的场景,RocketMQ client 向 Broker 拉取消息时,如果 Broker 返回 PULL_OFFSET_MOVED,client 就会通过异步线程(定时 10s 后执行)通知 Broker 更新 offset 为 nextPullOffset(上次 pull 消息时 broker 返回)。代码如下:

public void updateConsumeOffsetToBroker(MessageQueue mq, long offset, boolean isOneway) throws RemotingException,
MQBrokerException, InterruptedException, MQClientException {
    FindBrokerResult findBrokerResult = this.mQClientFactory.findBrokerAddressInSubscribe(mq.getBrokerName(), MixAll.MASTER_ID, true);
    if (null == findBrokerResult) {
        this.mQClientFactory.updateTopicRouteInfoFromNameServer(mq.getTopic());
        findBrokerResult = this.mQClientFactory.findBrokerAddressInSubscribe(mq.getBrokerName(), MixAll.MASTER_ID, false);
    }

    if (findBrokerResult != null) {
        //省略业务代码
    } else {
        throw new MQClientException("The broker[" + mq.getBrokerName() + "] not exist", null);
    }
}

 总结

  • Broker 挂了,客户端定时任务会判断到 Broker 离线,就会从本地缓存中移除(MQClientInstance#cleanOfflineBroker);

  • Broker 网络异常;

  • Broker 发生了主备切换,客户端获取 Broker 地址时切换还没有完

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值