gobreaker implements the Circuit Breaker pattern in Go.

gobreaker

GoDoc Build Status Coverage Status

gobreaker implements the Circuit Breaker pattern in Go.

Installation

go get github.com/sony/gobreaker

Usage

The struct CircuitBreaker is a state machine to prevent sending requests that are likely to fail. The function NewCircuitBreaker creates a new CircuitBreaker.

func NewCircuitBreaker(st Settings) *CircuitBreaker

You can configure CircuitBreaker by the struct Settings:

type Settings struct {
	Name          string
	MaxRequests   uint32
	Interval      time.Duration
	Timeout       time.Duration
	ReadyToTrip   func(counts Counts) bool
	OnStateChange func(name string, from State, to State)
}
  • Name is the name of the CircuitBreaker.

  • MaxRequests is the maximum number of requests allowed to pass through when the CircuitBreaker is half-open. If MaxRequests is 0, CircuitBreaker allows only 1 request.

  • Interval is the cyclic period of the closed state for CircuitBreaker to clear the internal Counts, described later in this section. If Interval is 0, CircuitBreaker doesn't clear the internal Counts during the closed state.

  • Timeout is the period of the open state, after which the state of CircuitBreaker becomes half-open. If Timeout is 0, the timeout value of CircuitBreaker is set to 60 seconds.

  • ReadyToTrip is called with a copy of Counts whenever a request fails in the closed state. If ReadyToTrip returns true, CircuitBreaker will be placed into the open state. If ReadyToTrip is nil, default ReadyToTrip is used. Default ReadyToTrip returns true when the number of consecutive failures is more than 5.

  • OnStateChange is called whenever the state of CircuitBreaker changes.

The struct Counts holds the numbers of requests and their successes/failures:

type Counts struct {
	Requests             uint32
	TotalSuccesses       uint32
	TotalFailures        uint32
	ConsecutiveSuccesses uint32
	ConsecutiveFailures  uint32
}

CircuitBreaker clears the internal Counts either on the change of the state or at the closed-state intervals. Counts ignores the results of the requests sent before clearing.

CircuitBreaker can wrap any function to send a request:

func (cb *CircuitBreaker) Execute(req func() (interface{}, error)) (interface{}, error)

The method Execute runs the given request if CircuitBreaker accepts it. Execute returns an error instantly if CircuitBreaker rejects the request. Otherwise, Execute returns the result of the request. If a panic occurs in the request, CircuitBreaker handles it as an error and causes the same panic again.

Example

var cb *breaker.CircuitBreaker

func Get(url string) ([]byte, error) {
	body, err := cb.Execute(func() (interface{}, error) {
		resp, err := http.Get(url)
		if err != nil {
			return nil, err
		}

		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return nil, err
		}

		return body, nil
	})
	if err != nil {
		return nil, err
	}

	return body.([]byte), nil
}

See example for details.

License

The MIT License (MIT)

See LICENSE for details.

Owner
Sony
Sony Group Corporation
Sony
Comments
  • Allow custom inspection of errors

    Allow custom inspection of errors

    Not all errors should be counted towards tripping the circuit breaker, this PR adds support for a custom inspection strategy to determine if an error should trip the circuit breaker or not.

  • breaker for host+service

    breaker for host+service

    i want to use gobreaker in my project, i have chained api that looks like this: request -> api gw -> oauth -> svc1 -> svc2 -> response

    oauth, svc1 can work on multiple hosts and if one fails another can work. doe i need to create different instances of breaker for such thing? or how to deal with such cases?

  • two-step pass check and outcome reporting

    two-step pass check and outcome reporting

    Hi, I'd like to have the possibility to check if a request can pass through and setting the outcome in separate steps, outside the Execute() method. This would be possible if the breaker had the following additional methods:

    • Allow() bool: would tell if the breaker is closed, or, in half open state, can the request pass through.
    • Success(): report a successful outcome
    • Failure(): report a failed outcome

    Allow() would be basically a visible wrapper around beforeRequest(), while Failure() and Success() around afterRequest().

    This would enable using the breaker in an asynchronous way, where the check for passing and reporting the outcome are not in a single control flow.

    I'd be happy to make a pull request.

  • Adjust counters to work with metrics usage

    Adjust counters to work with metrics usage

    With implementation in master, for a flapping breaker (for example, open - half-open) all counters are reset at the each state change. This means metrics would show 0 requests, 0 failures, which isn't ideal.

    This change stops resetting totals and implements ConsecutiveFailures which only resets when a request succeeds.

    This does not change how the breakers behave, only what is exported for metrics.

  • Does this really require go 1.12?

    Does this really require go 1.12?

    The go.mod file is set to work only with go 1.12. When building with go 1.11 I get errors around which version of Go is required. Is go 1.12 required? Can this limitation be removed from the go.mod?

  • Make CircuitBreaker.setState public.

    Make CircuitBreaker.setState public.

    Makes the CircuitBreaker.setState method public, to allow developers to implement functionality that can change the breaker's state from outside of the breaker.

  • May I request a new release with tag

    May I request a new release with tag

    Hi,

    Thanks a lot for your library, it's really helpful!

    When I check the release, the latest is 0.4.1, which was published in May 2019, but the latest merge was in Jan 2021, I can use go mod to get the latest commit change, however, when we request 3rd party library approval from my company, maybe it would not be approved, so may I request a new release with tag 0.4.2? Really appreciate it!

  • Tag SemVer releases?

    Tag SemVer releases?

    Hi! I notice that this project doesn't have any tagged releases. Would you mind adding some SemVer-compatible release tags? It would really, really help those of us using dep and similar tools.

  • two step circuit breaker

    two step circuit breaker

    providing a two-step circuit breaker where checking whether a request can proceed and reporting the otucome is separated.

    see previous discussions on the topic in #4

  • race conditions

    race conditions

    When i looked into the code I was wondering if this package would be aware of go routines. When it would be used in http handlers to handle calls of remote services , which is often the case in my implementation . The following test shows up that it is not aware of go routines even if there is a testcase in the package tests that tries to run them in parallel.

    ~/Desktop/Dev/go/sony/gobreaker:$ go test -race
    ==================
    WARNING: DATA RACE
    Read at 0x00c0001160d0 by goroutine 11:
      runtime.convT2Enoptr()
          /usr/local/go/src/runtime/iface.go:379 +0x0
      github.com/sony/gobreaker.TestCustomCircuitBreaker()
          /Users/rl/Desktop/Dev/go/sony/gobreaker/gobreaker_test.go:260 +0x11db
      testing.tRunner()
          /usr/local/go/src/testing/testing.go:909 +0x199
    
    Previous write at 0x00c0001160d0 by goroutine 12:
      github.com/sony/gobreaker.(*CircuitBreaker).beforeRequest()
          /Users/rl/Desktop/Dev/go/sony/gobreaker/gobreaker.go:56 +0x191
      github.com/sony/gobreaker.(*CircuitBreaker).Execute()
          /Users/rl/Desktop/Dev/go/sony/gobreaker/gobreaker.go:204 +0x63
      github.com/sony/gobreaker.succeedLater.func1()
          /Users/rl/Desktop/Dev/go/sony/gobreaker/gobreaker_test.go:38 +0x69
    
    Goroutine 11 (running) created at:
      testing.(*T).Run()
          /usr/local/go/src/testing/testing.go:960 +0x651
      testing.runTests.func1()
          /usr/local/go/src/testing/testing.go:1202 +0xa6
      testing.tRunner()
          /usr/local/go/src/testing/testing.go:909 +0x199
      testing.runTests()
          /usr/local/go/src/testing/testing.go:1200 +0x521
      testing.(*M).Run()
          /usr/local/go/src/testing/testing.go:1117 +0x2ff
      main.main()
          _testmain.go:58 +0x223
    
    Goroutine 12 (running) created at:
      github.com/sony/gobreaker.succeedLater()
          /Users/rl/Desktop/Dev/go/sony/gobreaker/gobreaker_test.go:37 +0x82
      github.com/sony/gobreaker.TestCustomCircuitBreaker()
          /Users/rl/Desktop/Dev/go/sony/gobreaker/gobreaker_test.go:258 +0x113a
      testing.tRunner()
          /usr/local/go/src/testing/testing.go:909 +0x199
    ==================
    --- FAIL: TestCustomCircuitBreaker (0.10s)
        testing.go:853: race detected during execution of test
    FAIL
    exit status 1
    FAIL	github.com/sony/gobreaker	2.213s
    

    What do you think about such a situation? Is it worth to invest in a PR to make it aware of go routines and in addition to that moving from the expensive sync.Mutex handling towards go channles so that always only one go routine is maintaining the counters and state?

  • Exported type for errors

    Exported type for errors

    Hi, we have a use case where we need to check the returned error, and we need to be able to see if it's returned from the CB.

    Can we open a PR with an exported error?

  • breaker per url

    breaker per url

    We would like to use circuit breaker pattern while integrating with 3rd party API's, however we want to isolate failures at integration + customer level.

    For example, example.com/test is one integration can be used by customer 1 and anotherexample.com/test is another integration used by customer 2.

    Let's say, when example.com/test is down and circuit trips after threshold, we do not want to affect customer 2 and others except customer of that particular integration which is down, is this possible?

    I guess challenge is we upfront do not know how many integrations will be needed so we need some dynamic way to define circuit breakers per combination of integration and customer (unique id of integration might be sufficient)

  • It will cause a deadlock when call breaker.Counts() method in the OnStateChange() method

    It will cause a deadlock when call breaker.Counts() method in the OnStateChange() method

    When the OnStateChange method is trigered, I want to know the breaker counts, so i call breaker.Counts(), but I get a deadlock The code is :

    OnStateChange: func(name string, from gobreaker.State, to gobreaker.State) {
    	// NOTICE:do not call breaker.Counts() in this method , it will cause a deadlock !!! 
    	counts := breaker.Counts()
    	logger.Infof("key: %s, breaker state has change, from %s to %s , the data --> %v", breaker.Name(), from.String(), to.String(), counts)
    }
    

    What method should I call when I want to know the counts number in OnStateChange method ?

  • Confusion about ErrTooManyRequests error

    Confusion about ErrTooManyRequests error

    Hi,

    Thanks a lot for your library, it's simple, yet powerful! :) Could you please clarify one confusion I have about ErrTooManyRequests error? I don't quite understand from the code when this error could happen. I see the if state == StateHalfOpen && cb.counts.Requests >= cb.maxRequests condition in the beforeRequest() method but from the rest of the code it doesn't look like it could ever be met. This is because we either get enough consecutive requests to trip circuit to close with this condition if cb.counts.ConsecutiveSuccesses >= cb.maxRequests { cb.setState(StateClosed, now) } or we go back to open state because of a single failure in onFailure(). Or did I misunderstand something?

GoLang-based client-side circuit breakers and helpers

Overview Example library for circuit breaking in GoLang. Written to support a blog post on https://www.wojno.com. Use this library in your SDK's to pr

Dec 5, 2021
A pluggable backend API that enforces the Event Sourcing Pattern for persisting & broadcasting application state changes
A pluggable backend API that enforces the Event Sourcing Pattern for persisting & broadcasting application state changes

A pluggable "Application State Gateway" that enforces the Event Sourcing Pattern for securely persisting & broadcasting application state ch

Nov 1, 2022
A convenient library to do a must pattern

must A convenient library to do a must pattern Problems Before Go 1.18, if you want to panic when the regular expression cannot compile, you need to d

Nov 15, 2022
Package tail implements file tailing with fsnotify.

Tail Package tail implements file tailing with fsnotify. Fork of nxadm/tail, simplified, reworked and optimized. Fully supports only posix-compatible

Nov 30, 2022
Package macho implements access to and creation of Mach-O object files.

go-macho [WIP] ?? Package macho implements access to and creation of Mach-O object files. Why ?? This package goes beyond the Go's debug/macho to: Cov

Sep 2, 2022
Cascadia package implements CSS selectors
Cascadia package implements CSS selectors

cascadia The Cascadia package implements CSS selectors for use with the parse tr

Jan 2, 2023
Convert dates from or to 31 calendars in Go. Implements the functions discussed in Reingold/Dershowitz 2018.

libcalcal - Calendrical calculations in Go About libcalcal implements in Go the functions described and presented in: Reingold, Edward M., and Nachum

Dec 30, 2021
Goya circuit is a circuit breaker mechanism implementation in microservices.

Goya-Circuit: 类似于Hystrix的熔断器实现 Goya circuit is a circuit breaker mechanism implementation in microservices. It can prevent the whole link avalanche ca

Mar 8, 2022
An efficient and feature complete Hystrix like Go implementation of the circuit breaker pattern.
An efficient and feature complete Hystrix like Go implementation of the circuit breaker pattern.

Circuit Circuit is an efficient and feature complete Hystrix like Go implementation of the circuit breaker pattern. Learn more about the problems Hyst

Dec 28, 2022
gRelay is an open source project written in Go that provides the circuit break pattern with a relay idea behind.
gRelay is an open source project written in Go that provides the circuit break pattern with a relay idea behind.

gRELAY gRelay is an open source project written in Go that provides: Circuit Break ✔️ Circuit Break + Relay ✔️ Concurrecny Safe ✔️ Getting start Insta

Sep 30, 2022
Go-ant-pattern: An ant pattern parser

go-ant-pattern - An ant pattern parser. Usage package main import ( "fmt" "github.com/cbuschka/go-ant-pattern" ) func main() { path := "

Dec 7, 2021
Leader-follower-pattern - Build leader-follower system pattern with etcd election

主备系统模式 原理 使用分布式锁实现主备节点系统。通过对分布式锁进行续期,保持长期锁, 从而使当前服务节点处于主服务节点 无法获取分布式锁的服务节点,则作为备选

Jan 24, 2022
this is a easy breaker by golang code

tfgo-breaker 1. Intro This is a easy breaker by golang code. U can use it in your project quickly. Support function break, timeout, auto dry-run. 2. D

Sep 17, 2022
this is a funny client for jsonrpc-client. it can support timeout,breaker ...

this is a funny client for jsonrpc-client. it can support timeout,breaker ...

Sep 17, 2022
A library that implements the outboxer pattern in go

Outboxer Outboxer is a go library that implements the outbox pattern. Getting Started Outboxer was designed to simplify the tough work of orchestratin

Dec 16, 2022
implements glob pattern match. This is implemented according to IEEE Std 1003.1-2017.

glob Package glob implements glob pattern match. This is implemented according to IEEE Std 1003.1-2017. Special Chars ?: A <question-mark> is a patter

Apr 10, 2022
Resequencer - A Go library that implements the resequencer pattern

resequencer A Go resequencer Introduction resequencer is a Go library that imple

Mar 19, 2022
My daily routine implements Atomic Pattern to the react app

RAGE (React Atomic Generator) Purpose My daily routine implements Atomic Pattern to the react app, I was doing that repeatedly, so the reason I create

Mar 8, 2022
This library implements the pub/sub pattern in a generic way. It uses Go's generic types to declare the type of the event.

observer This library implements the pub/sub pattern in a generic way. It uses Go's generic types to declare the type of the event. Usage go get githu

Nov 16, 2022
GoLang-based client-side circuit breakers and helpers

Overview Example library for circuit breaking in GoLang. Written to support a blog post on https://www.wojno.com. Use this library in your SDK's to pr

Dec 5, 2021