1 /* 2 * Copyright 2015 The gRPC Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package io.grpc.internal; 18 19 import static com.google.common.base.Preconditions.checkArgument; 20 21 import com.google.common.annotations.VisibleForTesting; 22 import java.util.Random; 23 import java.util.concurrent.TimeUnit; 24 25 /** 26 * Retry Policy for Transport reconnection. Initial parameters from 27 * https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md 28 * 29 * <p>TODO(carl-mastrangelo): add unit tests for this class 30 */ 31 public final class ExponentialBackoffPolicy implements BackoffPolicy { 32 public static final class Provider implements BackoffPolicy.Provider { 33 @Override get()34 public BackoffPolicy get() { 35 return new ExponentialBackoffPolicy(); 36 } 37 } 38 39 private Random random = new Random(); 40 private long initialBackoffNanos = TimeUnit.SECONDS.toNanos(1); 41 private long maxBackoffNanos = TimeUnit.MINUTES.toNanos(2); 42 private double multiplier = 1.6; 43 private double jitter = .2; 44 45 private long nextBackoffNanos = initialBackoffNanos; 46 47 @Override nextBackoffNanos()48 public long nextBackoffNanos() { 49 long currentBackoffNanos = nextBackoffNanos; 50 nextBackoffNanos = Math.min((long) (currentBackoffNanos * multiplier), maxBackoffNanos); 51 return currentBackoffNanos 52 + uniformRandom(-jitter * currentBackoffNanos, jitter * currentBackoffNanos); 53 } 54 uniformRandom(double low, double high)55 private long uniformRandom(double low, double high) { 56 checkArgument(high >= low); 57 double mag = high - low; 58 return (long) (random.nextDouble() * mag + low); 59 } 60 61 /* 62 * No guice and no flags means we get to implement these setters for testing ourselves. Do not 63 * call these from non-test code. 64 */ 65 66 @VisibleForTesting setRandom(Random random)67 ExponentialBackoffPolicy setRandom(Random random) { 68 this.random = random; 69 return this; 70 } 71 72 @VisibleForTesting setInitialBackoffNanos(long initialBackoffNanos)73 ExponentialBackoffPolicy setInitialBackoffNanos(long initialBackoffNanos) { 74 this.initialBackoffNanos = initialBackoffNanos; 75 return this; 76 } 77 78 @VisibleForTesting setMaxBackoffNanos(long maxBackoffNanos)79 ExponentialBackoffPolicy setMaxBackoffNanos(long maxBackoffNanos) { 80 this.maxBackoffNanos = maxBackoffNanos; 81 return this; 82 } 83 84 @VisibleForTesting setMultiplier(double multiplier)85 ExponentialBackoffPolicy setMultiplier(double multiplier) { 86 this.multiplier = multiplier; 87 return this; 88 } 89 90 @VisibleForTesting setJitter(double jitter)91 ExponentialBackoffPolicy setJitter(double jitter) { 92 this.jitter = jitter; 93 return this; 94 } 95 } 96 97