Sony Gobreaker Circuit Breaker
Wrap failing dependencies with sony/gobreaker, opening the circuit after consecutive failures and probing recovery in half-open.
Code
package main
import (
"errors"
"fmt"
"time"
"github.com/sony/gobreaker"
)
var errFlaky = errors.New("dependency flaky")
type flakyService struct{ failRate int }
func (s *flakyService) Call(n int) (string, error) {
if n%s.failRate == 0 {
return "", errFlaky
}
return "payload", nil
}
func newBreaker(name string) *gobreaker.CircuitBreaker {
return gobreaker.NewCircuitBreaker(gobreaker.Settings{
Name: name,
MaxRequests: 3, // 半开态最多放行 3 个试探
Interval: 10 * time.Second, // 闭合态计数窗口
Timeout: 5 * time.Second, // 打开态冷却时长
ReadyToTrip: func(counts gobreaker.Counts) bool {
return counts.ConsecutiveFailures >= 5
},
OnStateChange: func(name string, from gobreaker.State, to gobreaker.State) {
fmt.Printf("breaker %s: %s -> %s\n", name, from, to)
},
})
}
func guardedCall(cb *gobreaker.CircuitBreaker, svc *flakyService, n int) (string, error) {
out, err := cb.Execute(func() (interface{}, error) {
return svc.Call(n)
})
if err != nil {
return "", err
}
return out.(string), nil
}
func main() {
cb := newBreaker("flaky-api")
svc := &flakyService{failRate: 3}
for i := 1; i <= 12; i++ {
v, err := guardedCall(cb, svc, i)
fmt.Printf("call %02d -> value=%q err=%v\n", i, v, err)
}
}Report a problem with this exampleOpens a pre-filled issue on GitHub.