1/* 2 * 3 * Copyright 2017 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19package grpc 20 21import ( 22 "math/rand" 23 "time" 24) 25 26// DefaultBackoffConfig uses values specified for backoff in 27// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md. 28var DefaultBackoffConfig = BackoffConfig{ 29 MaxDelay: 120 * time.Second, 30 baseDelay: 1.0 * time.Second, 31 factor: 1.6, 32 jitter: 0.2, 33} 34 35// backoffStrategy defines the methodology for backing off after a grpc 36// connection failure. 37// 38// This is unexported until the gRPC project decides whether or not to allow 39// alternative backoff strategies. Once a decision is made, this type and its 40// method may be exported. 41type backoffStrategy interface { 42 // backoff returns the amount of time to wait before the next retry given 43 // the number of consecutive failures. 44 backoff(retries int) time.Duration 45} 46 47// BackoffConfig defines the parameters for the default gRPC backoff strategy. 48type BackoffConfig struct { 49 // MaxDelay is the upper bound of backoff delay. 50 MaxDelay time.Duration 51 52 // TODO(stevvooe): The following fields are not exported, as allowing 53 // changes would violate the current gRPC specification for backoff. If 54 // gRPC decides to allow more interesting backoff strategies, these fields 55 // may be opened up in the future. 56 57 // baseDelay is the amount of time to wait before retrying after the first 58 // failure. 59 baseDelay time.Duration 60 61 // factor is applied to the backoff after each retry. 62 factor float64 63 64 // jitter provides a range to randomize backoff delays. 65 jitter float64 66} 67 68func setDefaults(bc *BackoffConfig) { 69 md := bc.MaxDelay 70 *bc = DefaultBackoffConfig 71 72 if md > 0 { 73 bc.MaxDelay = md 74 } 75} 76 77func (bc BackoffConfig) backoff(retries int) time.Duration { 78 if retries == 0 { 79 return bc.baseDelay 80 } 81 backoff, max := float64(bc.baseDelay), float64(bc.MaxDelay) 82 for backoff < max && retries > 0 { 83 backoff *= bc.factor 84 retries-- 85 } 86 if backoff > max { 87 backoff = max 88 } 89 // Randomize backoff delays so that if a cluster of requests start at 90 // the same time, they won't operate in lockstep. 91 backoff *= 1 + bc.jitter*(rand.Float64()*2-1) 92 if backoff < 0 { 93 return 0 94 } 95 return time.Duration(backoff) 96} 97