gobreaker implements the Circuit Breaker pattern in Go.

Overview

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.

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.

    opened by dmarkhas 8
  • 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?

    opened by vtolstov 6
  • 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.

    opened by aryszka 6
  • 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.

    opened by ojarva 4
  • 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?

    opened by cep21 4
  • 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!

    opened by pelliu 2
  • 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.

    opened by akshayjshah 2
  • 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

    opened by aryszka 2
  • 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?

    opened by luedigernet 1
  • 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?

    opened by enrichman 1
  • [question/proposal] Monitoring

    [question/proposal] Monitoring

    What is the way to collect metrics for monitoring? It would be good to get more information about the statistic of circuit breaker than just status: open, half-open and closed.

    Count contains enough information about CB condition.

    type Counts struct {
    	Requests             uint32
    	TotalSuccesses       uint32
    	TotalFailures        uint32
    	ConsecutiveSuccesses uint32
    	ConsecutiveFailures  uint32
    }
    
    opened by lobotomist 0
  • 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.

    opened by Joel-Duff 2
  • 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)

    opened by menneni 0
  • 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 ?

    opened by Brandon-zhong 3
Owner
Sony
Sony Group Corporation
Sony
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

Chris Wojno 0 Dec 5, 2021
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

Coleman Word 29 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

Thanabodee Charoenpiriyakij 3 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

Aleksandr Razumov 14 Oct 20, 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

Bogdan Donchenko 7 Sep 2, 2022
Cascadia package implements CSS selectors

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

Andy Balholm 581 Nov 13, 2022
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

null 1 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

Anderson Lu 6 Mar 8, 2022
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

Jack Lindamood 673 Nov 17, 2022
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

null 31 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 := "

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

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

null 0 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

Lion 78 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 ...

Lion 20 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

Ítalo Vietro 97 Nov 25, 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

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

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

Teiva Harsanyi 4 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

Barnando Akbarto Hidayatullah 1 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

Leon Steinhäuser 6 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

Chris Wojno 0 Dec 5, 2021