Documentation ¶
Overview ¶
Package circuit implements the Circuit Breaker pattern. It will wrap a function call (typically one which uses remote services) and monitors for failures and/or time outs. When a threshold of failures or time outs has been reached, future calls to the function will not run. During this state, the breaker will periodically allow the function to run and, if it is successful, will start running the function again.
Circuit includes three types of circuit breakers:
A Threshold Breaker will trip when the failure count reaches a given threshold. It does not matter how long it takes to reach the threshold and the failures do not need to be consecutive.
A Consecutive Breaker will trip when the consecutive failure count reaches a given threshold. It does not matter how long it takes to reach the threshold, but the failures do need to be consecutive.
When wrapping blocks of code with a Breaker's Call() function, a time out can be specified. If the time out is reached, the breaker's Fail() function will be called.
Other types of circuit breakers can be easily built by creating a Breaker and adding a custom TripFunc. A TripFunc is called when a Breaker Fail()s and receives the breaker as an argument. It then returns true or false to indicate whether the breaker should trip.
The package also provides a wrapper around an http.Client that wraps all of the http.Client functions with a Breaker.
Index ¶
- Variables
- type Breaker
- func (cb *Breaker) Break()
- func (cb *Breaker) Call(circuit func() error, timeout time.Duration) error
- func (cb *Breaker) ConsecFailures() int64
- func (cb *Breaker) ErrorRate() float64
- func (cb *Breaker) Fail()
- func (cb *Breaker) Failures() int64
- func (cb *Breaker) Ready() bool
- func (cb *Breaker) Reset()
- func (cb *Breaker) ResetCounters()
- func (cb *Breaker) Subscribe() <-chan BreakerEvent
- func (cb *Breaker) Success()
- func (cb *Breaker) Successes() int64
- func (cb *Breaker) Trip()
- func (cb *Breaker) Tripped() bool
- type BreakerEvent
- type HTTPClient
- func (c *HTTPClient) Do(req *http.Request) (*http.Response, error)
- func (c *HTTPClient) Get(url string) (*http.Response, error)
- func (c *HTTPClient) Head(url string) (*http.Response, error)
- func (c *HTTPClient) Post(url string, bodyType string, body io.Reader) (*http.Response, error)
- func (c *HTTPClient) PostForm(url string, data url.Values) (*http.Response, error)
- type Panel
- type PanelEvent
- type Statter
- type TripFunc
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrBreakerOpen = errors.New("breaker open") ErrBreakerTimeout = errors.New("breaker time out") )
Error codes returned by Call
var ( // DefaultWindowTime is the default time the window covers, 10 seconds. DefaultWindowTime = time.Millisecond * 10000 // DefaultWindowBuckets is the default number of buckets the window holds, 10. DefaultWindowBuckets = 10 )
Functions ¶
This section is empty.
Types ¶
type Breaker ¶
type Breaker struct { // BackOff is the backoff policy that is used when determining if the breaker should // attempt to retry. A breaker created with NewBreaker will use an exponential backoff // policy by default. BackOff backoff.BackOff // ShouldTrip is a TripFunc that determines whether a Fail() call should trip the breaker. // A breaker created with NewBreaker will not have a ShouldTrip by default, and thus will // never automatically trip. ShouldTrip TripFunc // contains filtered or unexported fields }
Breaker is the base of a circuit breaker. It maintains failure and success counters as well as the event subscribers.
Example (Events) ¶
// This example demonstrates the BreakerTripped and BreakerReset callbacks. These are // available on all breaker types. breaker := NewThresholdBreaker(1) events := breaker.Subscribe() go func() { for { e := <-events switch e { case BreakerTripped: log.Println("breaker tripped") case BreakerReset: log.Println("breaker reset") case BreakerFail: log.Println("breaker fail") case BreakerReady: log.Println("breaker ready") } } }() breaker.Fail() breaker.Reset()
Output:
func NewBreaker ¶
func NewBreaker() *Breaker
NewBreaker creates a base breaker with an exponential backoff and no TripFunc
func NewConsecutiveBreaker ¶
NewConsecutiveBreaker creates a Breaker with a TripFunc that trips the breaker whenever the consecutive failure count meets the threshold.
func NewRateBreaker ¶
NewRateBreaker creates a Breaker with a TripFunc that trips the breaker whenever the error rate hits the threshold. The error rate is calculated as such: f = number of failures s = number of successes e = f / (f + s) The error rate is calculated over a sliding window of 10 seconds (by default) This breaker will not trip until there have been at least minSamples events.
func NewThresholdBreaker ¶
NewThresholdBreaker creates a Breaker with a TripFunc that trips the breaker whenever the failure count meets the threshold.
func (*Breaker) Break ¶
func (cb *Breaker) Break()
Break trips the circuit breaker and prevents it from auto resetting. Use this when manual control over the circuit breaker state is needed.
func (*Breaker) Call ¶
Call wraps a function the Breaker will protect. A failure is recorded whenever the function returns an error. If the called function takes longer than timeout to run, a failure will be recorded.
func (*Breaker) ConsecFailures ¶
ConsecFailures returns the number of consecutive failures that have occured.
func (*Breaker) ErrorRate ¶
ErrorRate returns the current error rate of the Breaker, expressed as a floating point number (e.g. 0.9 for 90%), since the last time the breaker was Reset.
func (*Breaker) Fail ¶
func (cb *Breaker) Fail()
Fail is used to indicate a failure condition the Breaker should record. It will increment the failure counters and store the time of the last failure. If the breaker has a TripFunc it will be called, tripping the breaker if necessary.
func (*Breaker) Ready ¶
Ready will return true if the circuit breaker is ready to call the function. It will be ready if the breaker is in a reset state, or if it is time to retry the call for auto resetting.
func (*Breaker) Reset ¶
func (cb *Breaker) Reset()
Reset will reset the circuit breaker. After Reset() is called, Tripped() will return false.
func (*Breaker) ResetCounters ¶
func (cb *Breaker) ResetCounters()
ResetCounters will reset only the failures, consecFailures, and success counters
func (*Breaker) Subscribe ¶
func (cb *Breaker) Subscribe() <-chan BreakerEvent
Subscribe returns a channel of BreakerEvents. Whenever the breaker changes state, the state will be sent over the channel. See BreakerEvent for the types of events.
func (*Breaker) Success ¶
func (cb *Breaker) Success()
Success is used to indicate a success condition the Breaker should record. If the success was triggered by a retry attempt, the breaker will be Reset().
type BreakerEvent ¶
type BreakerEvent int
BreakerEvent indicates the type of event received over an event channel
const ( // BreakerTripped is sent when a breaker trips BreakerTripped BreakerEvent = iota // BreakerReset is sent when a breaker resets BreakerReset BreakerEvent = iota // BreakerFail is sent when Fail() is called BreakerFail BreakerEvent = iota // BreakerReady is sent when the breaker enters the half open state and is ready to retry BreakerReady BreakerEvent = iota )
type HTTPClient ¶
type HTTPClient struct { Client *http.Client BreakerTripped func() BreakerReset func() BreakerLookup func(*HTTPClient, interface{}) *Breaker Panel *Panel // contains filtered or unexported fields }
HTTPClient is a wrapper around http.Client that provides circuit breaker capabilities.
By default, the client will use its defaultBreaker. A BreakerLookup function may be provided to allow different breakers to be used based on the circumstance. See the implementation of NewHostBasedHTTPClient for an example of this.
Example ¶
// This example sets up an HTTP client wrapped in a TimeoutBreaker. The breaker // will trip with the same behavior as TimeoutBreaker. client := NewHTTPClient(time.Second*5, 10, nil) resp, err := client.Get("http://example.com/resource.json") if err != nil { log.Fatal(err) } resource, err := ioutil.ReadAll(resp.Body) resp.Body.Close() if err != nil { log.Fatal(err) } fmt.Printf("%s", resource)
Output:
func NewHTTPClient ¶
NewHTTPClient provides a circuit breaker wrapper around http.Client. It wraps all of the regular http.Client functions. Specifying 0 for timeout will give a breaker that does not check for time outs.
func NewHTTPClientWithBreaker ¶
func NewHTTPClientWithBreaker(breaker *Breaker, timeout time.Duration, client *http.Client) *HTTPClient
NewHTTPClientWithBreaker provides a circuit breaker wrapper around http.Client. It wraps all of the regular http.Client functions using the provided Breaker.
func NewHostBasedHTTPClient ¶
func NewHostBasedHTTPClient(timeout time.Duration, threshold int64, client *http.Client) *HTTPClient
NewHostBasedHTTPClient provides a circuit breaker wrapper around http.Client. This client will use one circuit breaker per host parsed from the request URL. This allows you to use a single HTTPClient for multiple hosts with one host's breaker not affecting the other hosts.
func (*HTTPClient) Get ¶
func (c *HTTPClient) Get(url string) (*http.Response, error)
Get wraps http.Client Get()
func (*HTTPClient) Head ¶
func (c *HTTPClient) Head(url string) (*http.Response, error)
Head wraps http.Client Head()
type Panel ¶
type Panel struct { Statter Statter StatsPrefixf string Circuits map[string]*Breaker // contains filtered or unexported fields }
Panel tracks a group of circuit breakers by name.
Example ¶
// This example demonstrates using a Panel to aggregate and manage circuit breakers. breaker1 := NewThresholdBreaker(10) breaker2 := NewRateBreaker(0.95, 100) panel := NewPanel() panel.Add("breaker1", breaker1) panel.Add("breaker2", breaker2) // Elsewhere in the code ... b1, _ := panel.Get("breaker1") b1.Call(func() error { // Do some work return nil }, 0) b2, _ := panel.Get("breaker2") b2.Call(func() error { // Do some work return nil }, 0)
Output:
Example (Stats) ¶
// This example demonstrates how to push circuit breaker stats to statsd via a Panel. // This example uses g2s. Anything conforming to the Statter interface can be used. s, err := g2s.Dial("udp", "statsd-server:8125") if err != nil { log.Fatal(err) } breaker := NewThresholdBreaker(10) panel := NewPanel() panel.Statter = s panel.StatsPrefixf = "sys.production" panel.Add("x", breaker) breaker.Trip() // sys.production.circuit.x.tripped breaker.Reset() // sys.production.circuit.x.reset, sys.production.circuit.x.trip-time breaker.Fail() // sys.production.circuit.x.fail breaker.Ready() // sys.production.circuit.x.ready (if it's tripped and ready to retry)
Output:
func (*Panel) Get ¶
Get retrieves a circuit breaker by name. If no circuit breaker exists, it returns the NoOp one and sets ok to false.
func (*Panel) Subscribe ¶
func (p *Panel) Subscribe() <-chan PanelEvent
Subscribe returns a channel of PanelEvents. Whenever a breaker changes state, the PanelEvent will be sent over the channel. See BreakerEvent for the types of events.
type PanelEvent ¶
type PanelEvent struct { Name string Event BreakerEvent }
PanelEvent wraps a BreakerEvent and provides the string name of the breaker