RocketMQ-消息发送(三)、消息发送异常机制

消息发送高可用主要通过两个手段重试与Broker 规避。

首先消息发送端采用重试机制 ,由 retryTimesWhenSendFailed 指定同步方式重试次数,异步重试机制在收到消息发送结构后执行回调之前进行重试。由retryTimes WhenSendAsyncFailed 指定,接下来就是循环执行,选择消息队列 、发送消息,发送成功则返回,收到异常则重试。选择消息队列有两种方式

  1. sendLatencyFaultEnable=false ,默认不启用 Broker 故障延迟机制
  2. sendLatencyFaultEnable=true ,启用 Broker 障延迟机制

当为flase的时候,则默认直接调用TopicPublishInfo的selectOneMessageQueue方法,直接选用上一次执行失败的Broker。第一次执行时直接自增获取值。
那什么时候会产生Broker规避的情况呢:
假设在发消息的时候发生了Broker宕机的情况,我们知道路由算法中的消息队列是按Broker排序的,如果上一次根据路由算法选择的是宕机的Broker的第一个队列,那么随后的下次选择的是宕机的Broker的第二个队列,消息发送很有可能会失败,再次引发重试,带来不必要的性能损耗,那么我们就需要采用措施在一次消息发送失败之后暂时将Broker排除在消息队列选择范围外。
Broker规避的机制在MQFaultStrategy的selectOneMessageQueue中实现

publicMessageQueueselectOneMessageQueue(finalTopicPublishInfotpInfo,finalStringlastBrokerName){
		if(this.sendLatencyFaultEnable){
			try{
				intindex=tpInfo.getSendWhichQueue().getAndIncrement();
				for(inti=0;i0){
					finalMessageQueuemq=tpInfo.selectOneMessageQueue();
					if(notBestBroker!=null){
						mq.setBrokerName(notBestBroker);
						mq.setQueueId(tpInfo.getSendWhichQueue().getAndIncrement()%writeQueueNums);
					}
					returnmq;
				}else{
					latencyFaultTolerance.remove(notBestBroker);
				}
			}catch(Exceptione){
				log.error("Erroroccurredwhenselectingmessagequeue",e);
			}
			
			returntpInfo.selectOneMessageQueue();
		}
		returntpInfo.selectOneMessageQueue(lastBrokerName);
	}
  • 首先对消息队列进行轮询获取一个消息队列
  • 然后,验证该消息队列是否可用
    • 如果返回的MessageQueue是可用的,则移除latencyFaultTolerance关于该topic条目,表明该Broker故障已经恢复。
    • Broker故障延迟机制核心类
      //更新失败条目
    • void updateFaultItem(final T name,final long currentLatency,final long notAvailableDuration);
      //判断Broker是否可用
    • Boolean isAvailable(final T name);
      //移除Fault条目,意味着Broker重新参与路由计算
    • void remove(final T name);
      //尝试从规避的Broker中选择一个可用的Broker,如果没有找到,将返回null
    • T pickOneAtLeast();

你可能感兴趣的:(分布式,RocketMQ)