RocketMQ生产者如何规避故障Broker方式详解

 更新时间:2022年11月29日 10:21:48   作者:梦想实现家_Z  
这篇文章主要为大家介绍了RocketMQ生产者如何规避故障Broker方式详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

前言

在消息发送过程中,生产者从NameServer中获取到了指定Topic对应的Broker信息,在同步发送消息的代码中,如果消息发送失败,生产者默认是会重试两次的。那么Broker有问题的情况下,无论重试多少次都是没有意义的,消息生产者是如何规避这些故障Broker的呢?

收集故障Broker

我们在所有的发送消息源码中都可以找到这样一段代码,可在DefaultMQProducerImpl类中查找:

this.updateFaultItem(mq.getBrokerName(), endTimestamp - beginTimestampPrev, true);

无论是发送成功还是失败,RocketMQ生产者客户端都会做这一步操作:

// 发送成功的话,isolation传false,失败isolation传true
public void updateFaultItem(final String brokerName, final long currentLatency, boolean isolation) {
    if (this.sendLatencyFaultEnable) {
        long duration = computeNotAvailableDuration(isolation ? 30000 : currentLatency);
        this.latencyFaultTolerance.updateFaultItem(brokerName, currentLatency, duration);
    }
}
private long computeNotAvailableDuration(final long currentLatency) {
    for (int i = latencyMax.length - 1; i >= 0; i--) {
        if (currentLatency >= latencyMax[i])
            return this.notAvailableDuration[i];
    }
    return 0;
}
private long[] notAvailableDuration = {0L, 0L, 30000L, 60000L, 120000L, 180000L, 600000L};

如果Broker产生故障,那么会创建一个FaultItem对象记录故障的Broker,并把结果放进故障规避表faultItemTable中,数据格式如下:

"broker-a": {
  // broker名称
  "name": "broker-a",
  "currentLatency": 发送消息消耗的时间,毫秒值之差,
  // 解除规避的时间,绝对时间
  "startTimestamp": 时间戳毫秒值
},
"broker-b": {
  // broker名称
  "name": "broker-b",
  "currentLatency": 发送消息消耗的时间,毫秒值之差,
  // 解除规避的时间,绝对时间
  "startTimestamp": 时间戳毫秒值
}

发送成功的Broker设置的故障规避时间为0,发送失败的Broker将被设置为规避30秒;

选择Broker

MQFaultStrategy.selectOneMessageQueue()方法中,我们分三部分来分析如何选择Broker。

  • 轮询选择一个可用的Broker
// 轮询的基本套路,一个自增变量
int index = tpInfo.getSendWhichQueue().incrementAndGet();
for (int i = 0; i < tpInfo.getMessageQueueList().size(); i++) {
     // 通过对队列数量取模,获取选定的Broker所在的位置
     int pos = Math.abs(index++) % tpInfo.getMessageQueueList().size();
     if (pos < 0)
         pos = 0;
     MessageQueue mq = tpInfo.getMessageQueueList().get(pos);
     // 判断Broker是否在规避时间内,如果不在规避时间内,就选择这个Broker,否则继续循环直至所有Broker都在规避时间内
     if (latencyFaultTolerance.isAvailable(mq.getBrokerName()))
         return mq;
}

1.轮询的基本套路都是通过一个自增变量来对所有的Broker数量取模,这样就可以命中一个Broker;

2.针对命中的Broker判断是否在规避时间范围内,不在规避时间内就可以返回;否则只能进入第二个方案;

  • 选择一个相对延迟低的Broker
// 把所有规避列表中的Broker按延迟高低排序,并从延迟低的Broker中选择一个
final String notBestBroker = latencyFaultTolerance.pickOneAtLeast();
int writeQueueNums = tpInfo.getQueueIdByBroker(notBestBroker);
// 判断该Broker是否允许写消息
if (writeQueueNums > 0) {
    final MessageQueue mq = tpInfo.selectOneMessageQueue();
    if (notBestBroker != null) {
        mq.setBrokerName(notBestBroker);
        mq.setQueueId(tpInfo.getSendWhichQueue().incrementAndGet() % writeQueueNums);
    }
    // 返回选中的Broker
    return mq;
}

1.从规避列表中找到延时比较低的Broker;

2.判断该Broker是否允许写消息,允许写消息的话就直接返回,否则再进入下一个方案;

  • 默认的选择
return tpInfo.selectOneMessageQueue();

最后直接轮询一个Broker直接返回:

    public MessageQueue selectOneMessageQueue() {
        int index = this.sendWhichQueue.incrementAndGet();
        int pos = Math.abs(index) % this.messageQueueList.size();
        if (pos < 0)
            pos = 0;
        return this.messageQueueList.get(pos);
    }

该方案是默认方案,没有开启故障规避配置的话,所有Broker的选择都是使用的该方案;

小结

RocketMQ通过设置故障规避表的方式,把所有的Broker的延迟数据都保留在故障规避表中,根据该列表制定了以下几种策略:

1.优先选择不在规避时间范围内的Broker

2.如果所有Broker都在规避时间内,优先选择延迟低的Broker

3.如果依然没有选中合适的Broker,那么就直接挑一个Broker来用;

以上就是RocketMQ生产者如何规避故障Broker方式详解的详细内容,更多关于RocketMQ生产者规避故障Broker的资料请关注脚本之家其它相关文章!

相关文章

  • Java 实战范例之员工管理系统的实现

    Java 实战范例之员工管理系统的实现

    读万卷书不如行万里路,只学书上的理论是远远不够的,只有在实战中才能获得能力的提升,本篇文章手把手带你用java+vue+Springboot+ssm+mysql+maven+redis实现一个前后端分离的员工管理系统,大家可以在过程中查缺补漏,提升水平
    2021-11-11
  • Java编程之如何通过JSP实现头像自定义上传

    Java编程之如何通过JSP实现头像自定义上传

    之前做这个头像上传功能还是花了好多时间的,今天我将我的代码分享给大家,下面这篇文章主要给大家介绍了关于Java编程之如何通过JSP实现头像自定义上传的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2022-12-12
  • IDEA 2022最新激活码注册码超详细教程(亲测激活有效)

    IDEA 2022最新激活码注册码超详细教程(亲测激活有效)

    这篇文章主要介绍了IDEA 2022最新激活码超详细教程(亲测激活至2099年),本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • Java利用朴素贝叶斯分类算法实现信息分类

    Java利用朴素贝叶斯分类算法实现信息分类

    贝叶斯分类算法是统计学的一种分类方法,它是一类利用概率统计知识进行分类的算法。本文将利用朴素贝叶斯分类算法实现信息分类,需要的可以参考一下
    2022-06-06
  • JAVA如何转换树结构数据代码实例

    JAVA如何转换树结构数据代码实例

    这篇文章主要介绍了JAVA如何转换树结构数据代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • @Autowired注入为null问题原因分析

    @Autowired注入为null问题原因分析

    这篇文章主要介绍了@Autowired注入为null问题原因分析吗,小编觉得挺不错的,对日后比较有帮助,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-11-11
  • Java JNDI案例详解

    Java JNDI案例详解

    这篇文章主要介绍了Java JNDI案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • Java保留两位小数的几种写法总结

    Java保留两位小数的几种写法总结

    相信大家在平时做项目时,可能会有这样的业务需求: 页面或界面上展示的数据保留小数点后两位。 那么这篇文章小编就和大家分享了利用Java保留两位小数的几种写法,文章给出了详细的示例代码,对大家的学习和理解很有帮助,有需要的朋友们下面来一起学习学习下吧。
    2016-11-11
  • Java及nginx实现文件权限控制代码实例

    Java及nginx实现文件权限控制代码实例

    这篇文章主要介绍了Java及nginx实现文件权限控制代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • SpringBoot静态资源css,js,img配置方案

    SpringBoot静态资源css,js,img配置方案

    这篇文章主要介绍了SpringBoot静态资源css,js,img配置方案,下文给大家分享了三种解决方案,需要的朋友可以参考下
    2017-07-07

最新评论