backoff.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. package netutil
  2. import (
  3. "math/rand"
  4. "time"
  5. )
  6. // DefaultBackoffConfig uses values specified for backoff in common.
  7. var DefaultBackoffConfig = BackoffConfig{
  8. MaxDelay: 120 * time.Second,
  9. BaseDelay: 1.0 * time.Second,
  10. Factor: 1.6,
  11. Jitter: 0.2,
  12. }
  13. // Backoff defines the methodology for backing off after a call failure.
  14. type Backoff interface {
  15. // Backoff returns the amount of time to wait before the next retry given
  16. // the number of consecutive failures.
  17. Backoff(retries int) time.Duration
  18. }
  19. // BackoffConfig defines the parameters for the default backoff strategy.
  20. type BackoffConfig struct {
  21. // MaxDelay is the upper bound of backoff delay.
  22. MaxDelay time.Duration
  23. // baseDelay is the amount of time to wait before retrying after the first
  24. // failure.
  25. BaseDelay time.Duration
  26. // factor is applied to the backoff after each retry.
  27. Factor float64
  28. // jitter provides a range to randomize backoff delays.
  29. Jitter float64
  30. }
  31. /*
  32. // NOTE TODO avoid use unexcept config.
  33. func (bc *BackoffConfig) Fix() {
  34. md := bc.MaxDelay
  35. *bc = DefaultBackoffConfig
  36. if md > 0 {
  37. bc.MaxDelay = md
  38. }
  39. }
  40. */
  41. // Backoff returns the amount of time to wait before the next retry given
  42. // the number of consecutive failures.
  43. func (bc *BackoffConfig) Backoff(retries int) time.Duration {
  44. if retries == 0 {
  45. return bc.BaseDelay
  46. }
  47. backoff, max := float64(bc.BaseDelay), float64(bc.MaxDelay)
  48. for backoff < max && retries > 0 {
  49. backoff *= bc.Factor
  50. retries--
  51. }
  52. if backoff > max {
  53. backoff = max
  54. }
  55. // Randomize backoff delays so that if a cluster of requests start at
  56. // the same time, they won't operate in lockstep.
  57. backoff *= 1 + bc.Jitter*(rand.Float64()*2-1)
  58. if backoff < 0 {
  59. return 0
  60. }
  61. return time.Duration(backoff)
  62. }