backoff.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. package grpc
  2. import (
  3. "math/rand"
  4. "time"
  5. )
  6. // DefaultBackoffConfig uses values specified for backoff in
  7. // https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md.
  8. var (
  9. DefaultBackoffConfig = BackoffConfig{
  10. MaxDelay: 120 * time.Second,
  11. baseDelay: 1.0 * time.Second,
  12. factor: 1.6,
  13. jitter: 0.2,
  14. }
  15. )
  16. // backoffStrategy defines the methodology for backing off after a grpc
  17. // connection failure.
  18. //
  19. // This is unexported until the GRPC project decides whether or not to allow
  20. // alternative backoff strategies. Once a decision is made, this type and its
  21. // method may be exported.
  22. type backoffStrategy interface {
  23. // backoff returns the amount of time to wait before the next retry given
  24. // the number of consecutive failures.
  25. backoff(retries int) time.Duration
  26. }
  27. // BackoffConfig defines the parameters for the default GRPC backoff strategy.
  28. type BackoffConfig struct {
  29. // MaxDelay is the upper bound of backoff delay.
  30. MaxDelay time.Duration
  31. // TODO(stevvooe): The following fields are not exported, as allowing
  32. // changes would violate the current GRPC specification for backoff. If
  33. // GRPC decides to allow more interesting backoff strategies, these fields
  34. // may be opened up in the future.
  35. // baseDelay is the amount of time to wait before retrying after the first
  36. // failure.
  37. baseDelay time.Duration
  38. // factor is applied to the backoff after each retry.
  39. factor float64
  40. // jitter provides a range to randomize backoff delays.
  41. jitter float64
  42. }
  43. func setDefaults(bc *BackoffConfig) {
  44. md := bc.MaxDelay
  45. *bc = DefaultBackoffConfig
  46. if md > 0 {
  47. bc.MaxDelay = md
  48. }
  49. }
  50. func (bc BackoffConfig) backoff(retries int) (t time.Duration) {
  51. if retries == 0 {
  52. return bc.baseDelay
  53. }
  54. backoff, max := float64(bc.baseDelay), float64(bc.MaxDelay)
  55. for backoff < max && retries > 0 {
  56. backoff *= bc.factor
  57. retries--
  58. }
  59. if backoff > max {
  60. backoff = max
  61. }
  62. // Randomize backoff delays so that if a cluster of requests start at
  63. // the same time, they won't operate in lockstep.
  64. backoff *= 1 + bc.jitter*(rand.Float64()*2-1)
  65. if backoff < 0 {
  66. return 0
  67. }
  68. return time.Duration(backoff)
  69. }