]>
Commit | Line | Data |
---|---|---|
107c1cdb ND |
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 | ||
19 | // Package backoff implement the backoff strategy for gRPC. | |
20 | // | |
21 | // This is kept in internal until the gRPC project decides whether or not to | |
22 | // allow alternative backoff strategies. | |
23 | package backoff | |
24 | ||
25 | import ( | |
26 | "time" | |
27 | ||
28 | "google.golang.org/grpc/internal/grpcrand" | |
29 | ) | |
30 | ||
31 | // Strategy defines the methodology for backing off after a grpc connection | |
32 | // failure. | |
33 | // | |
34 | type Strategy interface { | |
35 | // Backoff returns the amount of time to wait before the next retry given | |
36 | // the number of consecutive failures. | |
37 | Backoff(retries int) time.Duration | |
38 | } | |
39 | ||
40 | const ( | |
41 | // baseDelay is the amount of time to wait before retrying after the first | |
42 | // failure. | |
43 | baseDelay = 1.0 * time.Second | |
44 | // factor is applied to the backoff after each retry. | |
45 | factor = 1.6 | |
46 | // jitter provides a range to randomize backoff delays. | |
47 | jitter = 0.2 | |
48 | ) | |
49 | ||
50 | // Exponential implements exponential backoff algorithm as defined in | |
51 | // https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md. | |
52 | type Exponential struct { | |
53 | // MaxDelay is the upper bound of backoff delay. | |
54 | MaxDelay time.Duration | |
55 | } | |
56 | ||
57 | // Backoff returns the amount of time to wait before the next retry given the | |
58 | // number of retries. | |
59 | func (bc Exponential) Backoff(retries int) time.Duration { | |
60 | if retries == 0 { | |
61 | return baseDelay | |
62 | } | |
63 | backoff, max := float64(baseDelay), float64(bc.MaxDelay) | |
64 | for backoff < max && retries > 0 { | |
65 | backoff *= factor | |
66 | retries-- | |
67 | } | |
68 | if backoff > max { | |
69 | backoff = max | |
70 | } | |
71 | // Randomize backoff delays so that if a cluster of requests start at | |
72 | // the same time, they won't operate in lockstep. | |
73 | backoff *= 1 + jitter*(grpcrand.Float64()*2-1) | |
74 | if backoff < 0 { | |
75 | return 0 | |
76 | } | |
77 | return time.Duration(backoff) | |
78 | } |