RetryPolicies.java
上传用户:quxuerui
上传日期:2018-01-08
资源大小:41811k
文件大小:8k
源码类别:

网格计算

开发平台:

Java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one
  3.  * or more contributor license agreements.  See the NOTICE file
  4.  * distributed with this work for additional information
  5.  * regarding copyright ownership.  The ASF licenses this file
  6.  * to you under the Apache License, Version 2.0 (the
  7.  * "License"); you may not use this file except in compliance
  8.  * with the License.  You may obtain a copy of the License at
  9.  *
  10.  *     http://www.apache.org/licenses/LICENSE-2.0
  11.  *
  12.  * Unless required by applicable law or agreed to in writing, software
  13.  * distributed under the License is distributed on an "AS IS" BASIS,
  14.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15.  * See the License for the specific language governing permissions and
  16.  * limitations under the License.
  17.  */
  18. package org.apache.hadoop.io.retry;
  19. import java.util.HashMap;
  20. import java.util.Map;
  21. import java.util.Random;
  22. import java.util.Set;
  23. import java.util.Map.Entry;
  24. import java.util.concurrent.TimeUnit;
  25. import org.apache.hadoop.ipc.RemoteException;
  26. /**
  27.  * <p>
  28.  * A collection of useful implementations of {@link RetryPolicy}.
  29.  * </p>
  30.  */
  31. public class RetryPolicies {
  32.   
  33.   /**
  34.    * <p>
  35.    * Try once, and fail by re-throwing the exception.
  36.    * This corresponds to having no retry mechanism in place.
  37.    * </p>
  38.    */
  39.   public static final RetryPolicy TRY_ONCE_THEN_FAIL = new TryOnceThenFail();
  40.   
  41.   /**
  42.    * <p>
  43.    * Try once, and fail silently for <code>void</code> methods, or by
  44.    * re-throwing the exception for non-<code>void</code> methods.
  45.    * </p>
  46.    */
  47.   public static final RetryPolicy TRY_ONCE_DONT_FAIL = new TryOnceDontFail();
  48.   
  49.   /**
  50.    * <p>
  51.    * Keep trying forever.
  52.    * </p>
  53.    */
  54.   public static final RetryPolicy RETRY_FOREVER = new RetryForever();
  55.   
  56.   /**
  57.    * <p>
  58.    * Keep trying a limited number of times, waiting a fixed time between attempts,
  59.    * and then fail by re-throwing the exception.
  60.    * </p>
  61.    */
  62.   public static final RetryPolicy retryUpToMaximumCountWithFixedSleep(int maxRetries, long sleepTime, TimeUnit timeUnit) {
  63.     return new RetryUpToMaximumCountWithFixedSleep(maxRetries, sleepTime, timeUnit);
  64.   }
  65.   
  66.   /**
  67.    * <p>
  68.    * Keep trying for a maximum time, waiting a fixed time between attempts,
  69.    * and then fail by re-throwing the exception.
  70.    * </p>
  71.    */
  72.   public static final RetryPolicy retryUpToMaximumTimeWithFixedSleep(long maxTime, long sleepTime, TimeUnit timeUnit) {
  73.     return new RetryUpToMaximumTimeWithFixedSleep(maxTime, sleepTime, timeUnit);
  74.   }
  75.   
  76.   /**
  77.    * <p>
  78.    * Keep trying a limited number of times, waiting a growing amount of time between attempts,
  79.    * and then fail by re-throwing the exception.
  80.    * The time between attempts is <code>sleepTime</code> mutliplied by the number of tries so far.
  81.    * </p>
  82.    */
  83.   public static final RetryPolicy retryUpToMaximumCountWithProportionalSleep(int maxRetries, long sleepTime, TimeUnit timeUnit) {
  84.     return new RetryUpToMaximumCountWithProportionalSleep(maxRetries, sleepTime, timeUnit);
  85.   }
  86.   
  87.   /**
  88.    * <p>
  89.    * Keep trying a limited number of times, waiting a growing amount of time between attempts,
  90.    * and then fail by re-throwing the exception.
  91.    * The time between attempts is <code>sleepTime</code> mutliplied by a random
  92.    * number in the range of [0, 2 to the number of retries)
  93.    * </p>
  94.    */
  95.   public static final RetryPolicy exponentialBackoffRetry(
  96.       int maxRetries, long sleepTime, TimeUnit timeUnit) {
  97.     return new ExponentialBackoffRetry(maxRetries, sleepTime, timeUnit);
  98.   }
  99.   
  100.   /**
  101.    * <p>
  102.    * Set a default policy with some explicit handlers for specific exceptions.
  103.    * </p>
  104.    */
  105.   public static final RetryPolicy retryByException(RetryPolicy defaultPolicy,
  106.                                                    Map<Class<? extends Exception>, RetryPolicy> exceptionToPolicyMap) {
  107.     return new ExceptionDependentRetry(defaultPolicy, exceptionToPolicyMap);
  108.   }
  109.   
  110.   /**
  111.    * <p>
  112.    * A retry policy for RemoteException
  113.    * Set a default policy with some explicit handlers for specific exceptions.
  114.    * </p>
  115.    */
  116.   public static final RetryPolicy retryByRemoteException(
  117.       RetryPolicy defaultPolicy,
  118.       Map<Class<? extends Exception>, RetryPolicy> exceptionToPolicyMap) {
  119.     return new RemoteExceptionDependentRetry(defaultPolicy, exceptionToPolicyMap);
  120.   }
  121.   
  122.   static class TryOnceThenFail implements RetryPolicy {
  123.     public boolean shouldRetry(Exception e, int retries) throws Exception {
  124.       throw e;
  125.     }
  126.   }
  127.   static class TryOnceDontFail implements RetryPolicy {
  128.     public boolean shouldRetry(Exception e, int retries) throws Exception {
  129.       return false;
  130.     }
  131.   }
  132.   
  133.   static class RetryForever implements RetryPolicy {
  134.     public boolean shouldRetry(Exception e, int retries) throws Exception {
  135.       return true;
  136.     }
  137.   }
  138.   
  139.   static abstract class RetryLimited implements RetryPolicy {
  140.     int maxRetries;
  141.     long sleepTime;
  142.     TimeUnit timeUnit;
  143.     
  144.     public RetryLimited(int maxRetries, long sleepTime, TimeUnit timeUnit) {
  145.       this.maxRetries = maxRetries;
  146.       this.sleepTime = sleepTime;
  147.       this.timeUnit = timeUnit;
  148.     }
  149.     public boolean shouldRetry(Exception e, int retries) throws Exception {
  150.       if (retries >= maxRetries) {
  151.         throw e;
  152.       }
  153.       try {
  154.         timeUnit.sleep(calculateSleepTime(retries));
  155.       } catch (InterruptedException ie) {
  156.         // retry
  157.       }
  158.       return true;
  159.     }
  160.     
  161.     protected abstract long calculateSleepTime(int retries);
  162.   }
  163.   
  164.   static class RetryUpToMaximumCountWithFixedSleep extends RetryLimited {
  165.     public RetryUpToMaximumCountWithFixedSleep(int maxRetries, long sleepTime, TimeUnit timeUnit) {
  166.       super(maxRetries, sleepTime, timeUnit);
  167.     }
  168.     
  169.     @Override
  170.     protected long calculateSleepTime(int retries) {
  171.       return sleepTime;
  172.     }
  173.   }
  174.   
  175.   static class RetryUpToMaximumTimeWithFixedSleep extends RetryUpToMaximumCountWithFixedSleep {
  176.     public RetryUpToMaximumTimeWithFixedSleep(long maxTime, long sleepTime, TimeUnit timeUnit) {
  177.       super((int) (maxTime / sleepTime), sleepTime, timeUnit);
  178.     }
  179.   }
  180.   
  181.   static class RetryUpToMaximumCountWithProportionalSleep extends RetryLimited {
  182.     public RetryUpToMaximumCountWithProportionalSleep(int maxRetries, long sleepTime, TimeUnit timeUnit) {
  183.       super(maxRetries, sleepTime, timeUnit);
  184.     }
  185.     
  186.     @Override
  187.     protected long calculateSleepTime(int retries) {
  188.       return sleepTime * (retries + 1);
  189.     }
  190.   }
  191.   
  192.   static class ExceptionDependentRetry implements RetryPolicy {
  193.     RetryPolicy defaultPolicy;
  194.     Map<Class<? extends Exception>, RetryPolicy> exceptionToPolicyMap;
  195.     
  196.     public ExceptionDependentRetry(RetryPolicy defaultPolicy,
  197.                                    Map<Class<? extends Exception>, RetryPolicy> exceptionToPolicyMap) {
  198.       this.defaultPolicy = defaultPolicy;
  199.       this.exceptionToPolicyMap = exceptionToPolicyMap;
  200.     }
  201.     public boolean shouldRetry(Exception e, int retries) throws Exception {
  202.       RetryPolicy policy = exceptionToPolicyMap.get(e.getClass());
  203.       if (policy == null) {
  204.         policy = defaultPolicy;
  205.       }
  206.       return policy.shouldRetry(e, retries);
  207.     }
  208.     
  209.   }
  210.   
  211.   static class RemoteExceptionDependentRetry implements RetryPolicy {
  212.     RetryPolicy defaultPolicy;
  213.     Map<String, RetryPolicy> exceptionNameToPolicyMap;
  214.     
  215.     public RemoteExceptionDependentRetry(RetryPolicy defaultPolicy,
  216.                                    Map<Class<? extends Exception>,
  217.                                    RetryPolicy> exceptionToPolicyMap) {
  218.       this.defaultPolicy = defaultPolicy;
  219.       this.exceptionNameToPolicyMap = new HashMap<String, RetryPolicy>();
  220.       for (Entry<Class<? extends Exception>, RetryPolicy> e :
  221.           exceptionToPolicyMap.entrySet()) {
  222.         exceptionNameToPolicyMap.put(e.getKey().getName(), e.getValue());
  223.       }
  224.     }
  225.     public boolean shouldRetry(Exception e, int retries) throws Exception {
  226.       RetryPolicy policy = null;
  227.       if (e instanceof RemoteException) {
  228.         policy = exceptionNameToPolicyMap.get(
  229.             ((RemoteException) e).getClassName());
  230.       }
  231.       if (policy == null) {
  232.         policy = defaultPolicy;
  233.       }
  234.       return policy.shouldRetry(e, retries);
  235.     }
  236.   }
  237.   
  238.   static class ExponentialBackoffRetry extends RetryLimited {
  239.     private Random r = new Random();
  240.     public ExponentialBackoffRetry(
  241.         int maxRetries, long sleepTime, TimeUnit timeUnit) {
  242.       super(maxRetries, sleepTime, timeUnit);
  243.     }
  244.     
  245.     @Override
  246.     protected long calculateSleepTime(int retries) {
  247.       return sleepTime*r.nextInt(1<<(retries+1));
  248.     }
  249.   }
  250. }