circuitbreaker icon indicating copy to clipboard operation
circuitbreaker copied to clipboard

How long dose it recover when it breaker

Open YuanWeiKang opened this issue 5 years ago • 4 comments
trafficstars

it's code

func TestBreaker22(t *testing.T) {
	brk := NewBreakerWithOptions(&Options{
		ShouldTrip: RateTripFunc(0.6, 100),
	})
	flag := 0
	start := time.Now().UnixNano()
	for i := 0; i < 200; i++ {
		err := brk.Call(func() error {
			return testDoSomething(flag)
		}, 0)

		last := atomic.LoadInt64(&brk.lastFailure)
		since := brk.Clock.Now().Sub(time.Unix(0, last))
		trip := atomic.LoadInt32(&brk.tripped)
		fmt.Printf("i:%d, trip:%d, last:%d, since:%+v, backOff:%+v, flag:%d, error:%s\n", i, trip, last, since, brk.nextBackOff, flag, err)

		if err == nil && brk.tripped == 0 {
			fmt.Printf("i:%d, trip:%d, duration:%d\n", i, brk.tripped, time.Now().UnixNano()-start)
			//break
		}
		if err != nil && strings.Contains(err.Error(), "breaker open") {
			flag = 1
			//time.Sleep(200 * time.Millisecond)
		}
	}
}

func testDoSomething(flag int) error {
	if flag == 0 {
		return fmt.Errorf("bad request")
	} else {
		return nil
	}
}

How do I calculate the recovery time?

YuanWeiKang avatar Mar 20 '20 11:03 YuanWeiKang

I'm not sure what the recovery time is but it looks like it's not configurable and not documented.

macdabby avatar Jun 04 '20 15:06 macdabby

This is where it is defined: https://github.com/rubyist/circuitbreaker/blob/4afb8473475bafc430776dcaafd1e6d84a8032ad/circuitbreaker.go#L391

macdabby avatar Jun 04 '20 15:06 macdabby

it seems that it's using exponential backoff by default: https://github.com/rubyist/circuitbreaker/blob/4afb8473475bafc430776dcaafd1e6d84a8032ad/circuitbreaker.go#L95

macdabby avatar Jun 04 '20 15:06 macdabby

The backoff time is defined by backing backing.ExponentialBackOff , it's assigned with default values and further customized at:

https://github.com/rubyist/circuitbreaker/blob/4afb8473475bafc430776dcaafd1e6d84a8032ad/circuitbreaker.go#L139-L146

The actual backoff time is controlled by ExponentialBackOff type. Entire logic is documented and explained in official documentation. Following is the snippet from the documentation that explains this logic

Example: Given the following default arguments, for 10 tries the sequence will be, and assuming we go over the MaxElapsedTime on the 10th try:

Request #  RetryInterval (seconds)  Randomized Interval (seconds)

 1          0.5                     [0.25,   0.75]
 2          0.75                    [0.375,  1.125]
 3          1.125                   [0.562,  1.687]
 4          1.687                   [0.8435, 2.53]
 5          2.53                    [1.265,  3.795]
 6          3.795                   [1.897,  5.692]
 7          5.692                   [2.846,  8.538]
 8          8.538                   [4.269, 12.807]
 9         12.807                   [6.403, 19.210]
10         19.210                   backoff.Stop

It's also worth noting that default value of InitialInterval is 500ms and that of MaxElapsedTime is 0 in circuitbreaker. Thus table above gives you each backoff duration window with the exception that it doesn't stop growing at Request # 10 since the value of MaxElapsedTime is 0 by default in circuitbreaker. It'll keep on backing off exponentially with same logic till it attains max value of 1 minute (default from backoff) thus leading to final randomized interval between 30 and 90 seconds with default values from breaker.

You can customize these values if you wish to. Use NewBreakerWithOptions directly instead of convenient NewXXXX variant wrappers and pass your own instance of ExponentialBackOff with specific values as per your needs.

apundir avatar Aug 04 '20 16:08 apundir