负载均衡策略RetryRule

351 阅读1分钟

小知识,大挑战!本文正在参与「程序员必备小知识」创作活动

16负载均衡策略RetryRule

RetryRule

RetryRule:

/*
*
* Copyright 2013 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.netflix.loadbalancer;

import com.netflix.client.config.IClientConfig;

/**
 * Given that
 * {@link IRule} can be cascaded, this {@link RetryRule} class allows adding a retry logic to an existing Rule.
 * 
 * @author stonse
 * 
 */
public class RetryRule extends AbstractLoadBalancerRule {
   IRule subRule = new RoundRobinRule();
   long maxRetryMillis = 500;

   public RetryRule() {
   }

   public RetryRule(IRule subRule) {
      this.subRule = (subRule != null) ? subRule : new RoundRobinRule();
   }

   public RetryRule(IRule subRule, long maxRetryMillis) {
      this.subRule = (subRule != null) ? subRule : new RoundRobinRule();
      this.maxRetryMillis = (maxRetryMillis > 0) ? maxRetryMillis : 500;
   }

   public void setRule(IRule subRule) {
      this.subRule = (subRule != null) ? subRule : new RoundRobinRule();
   }

   public IRule getRule() {
      return subRule;
   }

   public void setMaxRetryMillis(long maxRetryMillis) {
      if (maxRetryMillis > 0) {
         this.maxRetryMillis = maxRetryMillis;
      } else {
         this.maxRetryMillis = 500;
      }
   }

   public long getMaxRetryMillis() {
      return maxRetryMillis;
   }

   
   
   @Override
   public void setLoadBalancer(ILoadBalancer lb) {       
      super.setLoadBalancer(lb);
      subRule.setLoadBalancer(lb);
   }

   /*
    * Loop if necessary. Note that the time CAN be exceeded depending on the
    * subRule, because we're not spawning additional threads and returning
    * early.
    */
   public Server choose(ILoadBalancer lb, Object key) {
      long requestTime = System.currentTimeMillis();
      long deadline = requestTime + maxRetryMillis;

      Server answer = null;

      answer = subRule.choose(key);

      if (((answer == null) || (!answer.isAlive()))
            && (System.currentTimeMillis() < deadline)) {

         InterruptTask task = new InterruptTask(deadline
               - System.currentTimeMillis());

         while (!Thread.interrupted()) {
            answer = subRule.choose(key);

            if (((answer == null) || (!answer.isAlive()))
                  && (System.currentTimeMillis() < deadline)) {
               /* pause and retry hoping it's transient */
               Thread.yield();
            } else {
               break;
            }
         }

         task.cancel();
      }

      if ((answer == null) || (!answer.isAlive())) {
         return null;
      } else {
         return answer;
      }
   }

   @Override
   public Server choose(Object key) {
      return choose(getLoadBalancer(), key);
   }

   @Override
   public void initWithNiwsConfig(IClientConfig clientConfig) {
   }
}

该策略实现了一个具备重试机制的实例选择功能。内部定义了IRule对象,默认是RoundRobinRule实例。在choose方法中实现了对内部定义的策略进行反复尝试的策略,如果能够选择到具体的服务实例就返回,如果选择不到就根据设置的尝试结束时间阈值,当超过该阈值就返回null。

这就是负载均衡策略RetryRule的大体逻辑了