Documentation
¶
Overview ¶
Package circuitbreaker implements CircuitBreaker pattern (see https://docs.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker) for http requests.
Package provides light-weight and extendable implementation, fully compatible with standard HTTP Go library.
Index ¶
- Variables
- type CircuitBreaker
- func (cb *CircuitBreaker) Close()
- func (cb *CircuitBreaker) Get(url string) (resp *http.Response, err error)
- func (cb *CircuitBreaker) GetState() State
- func (cb *CircuitBreaker) GetWithContext(ctx context.Context, url string) (resp *http.Response, err error)
- func (cb *CircuitBreaker) Post(url, contentType string, body io.Reader) (resp *http.Response, err error)
- func (cb *CircuitBreaker) PostWithContext(ctx context.Context, url, contentType string, body io.Reader) (resp *http.Response, err error)
- func (cb *CircuitBreaker) RoundTrip(req *http.Request) (*http.Response, error)
- func (cb *CircuitBreaker) String() string
- type DefaultFailureDetector
- type FailureDetector
- type Recoverer
- type RecovererConseqSuccess
- type State
- type Trigger
- type TriggerConseqFailure
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var DefaultHalfOpenPassRate int32 = 5
DefaultHalfOpenPassRate specifies how many requests should be skipped before the passing one when circuit breaker is in Half-Open state.
Default is 0, which means no requests are going to be skipped.
var DefaultRecoverer = &RecovererConseqSuccess{Threshold: 5}
DefaultRecoverer used if no recoverer spacified for circuit breaker instance
var DefaultTimeout = 10 * time.Second
DefaultTimeout is the default value for the Open state time
var DefaultTimeoutJitter = 300 * time.Millisecond
DefaultTimeoutJitter is default value for the jitter to distribute the time for cliens get back to full consumption power
var DefaultTrigger = &TriggerConseqFailure{Threshold: 5}
DefaultTrigger used if no trigger specified for circuit breaker instance
var ErrOpenState = errors.New("circuit breaker open")
ErrOpenState issued then circuit breaker is in the open state
Functions ¶
This section is empty.
Types ¶
type CircuitBreaker ¶
type CircuitBreaker struct {
// Timeout specifies the time to keep circuit breaker in Open state
// before switch to Half-Open
Timeout time.Duration
// Jitter specifies the time fluctuation to extend the timeout
// jitter helps to distribute the multiple circuit breakers closing moments
// and avoid the instant overload for target service
Jitter time.Duration
// HalfOpenPassRate specifies the ratio of requiests to pass in Half-Open state
// to minimize the load when circuit breaker checks the target service for availablity
// If specified, circuit breaker will skip N incoming requests
// the next one will pass.
// For example if HalfOpenPassRate=5, five requests will be skipped, 6th will pass.
// If HalfOpenPassRate=0 (default) all requests will pass
HalfOpenPassRate int32
// OnStateChange calls on each status chsnge and passes the news state value
OnStateChange func(State)
// Trigger makes the decision when to open circuit breaker based on requests results .
// If nil, DefaultTrigger is used
Trigger Trigger
// Recoverer makes decision when to close cirsiot breacker absed on requests results.
// If nil, DefaultRecoverer is used
Recoverer Recoverer
// FailureDetector makes decision if request is filed or not.
// If nil, DefaultFailureDetector is used
FailureDetector FailureDetector
// The transport used to perform proxy requests.
// If nil, http.DefaultTransport is used
Transport http.RoundTripper
// contains filtered or unexported fields
}
CircuitBreaker is a wrapper on HTTP transport, which implements Circuit Breaker pattern
Example (HttpRequest) ¶
The following example shows how to use CircuitBreaker for the regular Http Request
package main
import (
"fmt"
"io/ioutil"
"log"
"time"
"github.com/vasmik/circuitbreaker"
)
func main() {
// Create circuit breaker instance
cb := &circuitbreaker.CircuitBreaker{
Trigger: &circuitbreaker.TriggerConseqFailure{Threshold: 3},
Recoverer: &circuitbreaker.RecovererConseqSuccess{Threshold: 3},
Timeout: 10 * time.Second,
Jitter: 300 * time.Millisecond,
HalfOpenPassRate: 5,
OnStateChange: func(s circuitbreaker.State) {
log.Printf("cirquitbreaker state changed %s", s)
},
}
// Use circuit breaker instead of regular http.Get
res, err := cb.Get("http://someservice.com/api/endpoint")
if err != nil {
switch err {
case circuitbreaker.ErrOpenState:
// Falback code
log.Println("This is a fallback result")
default:
// Error handling
log.Printf("can't call remote service: %v", err)
}
}
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(body)
}
Example (HttpRequestDefault) ¶
The following example shows how to use default CircuitBreaker for the regular Http Request
package main
import (
"fmt"
"io/ioutil"
"log"
"github.com/vasmik/circuitbreaker"
)
func main() {
// Create circuit breaker instance
cb := &circuitbreaker.CircuitBreaker{}
// Use circuit breaker instead of regular http.Get
res, err := cb.Get("http://someservice.com/api/endpoint")
if err != nil {
switch err {
case circuitbreaker.ErrOpenState:
// Falback code
log.Println("This is a fallback result")
default:
// Error handling
log.Printf("can't call remote service: %v", err)
}
}
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(body)
}
Example (ReverseProxy) ¶
package main
import (
"log"
"net/http"
"net/http/httputil"
"github.com/vasmik/circuitbreaker"
)
func main() {
// Create reverse proxy with circuit breaker
revProxy := &httputil.ReverseProxy{
Transport: &circuitbreaker.CircuitBreaker{
OnStateChange: func(s circuitbreaker.State) {
log.Printf("cirquitbreaker state changed %s", s)
},
},
ErrorHandler: func(rw http.ResponseWriter, r *http.Request, err error) {
switch err {
case circuitbreaker.ErrOpenState:
// Fallback code
rw.WriteHeader(http.StatusOK)
rw.Write([]byte("Fallback response"))
default:
rw.WriteHeader(http.StatusBadGateway)
}
log.Printf("reverse proxy error: %v", err)
},
}
// Use reverse proxy
handler := func(rw http.ResponseWriter, r *http.Request) {
revProxy.ServeHTTP(rw, r)
}
_ = handler
}
func (*CircuitBreaker) Close ¶
func (cb *CircuitBreaker) Close()
Close allows to manually close the cirquit breaker failure counters will be resetted
func (*CircuitBreaker) Get ¶
func (cb *CircuitBreaker) Get(url string) (resp *http.Response, err error)
Get wraps the http.Get with circuit breaker
func (*CircuitBreaker) GetState ¶
func (cb *CircuitBreaker) GetState() State
GetState returns current state
func (*CircuitBreaker) GetWithContext ¶
func (cb *CircuitBreaker) GetWithContext(ctx context.Context, url string) (resp *http.Response, err error)
GetWithContext wraps the http.Get with circuit breaker and context
func (*CircuitBreaker) Post ¶
func (cb *CircuitBreaker) Post(url, contentType string, body io.Reader) (resp *http.Response, err error)
Post wraps the http.Post with circuit breaker
func (*CircuitBreaker) PostWithContext ¶
func (cb *CircuitBreaker) PostWithContext(ctx context.Context, url, contentType string, body io.Reader) (resp *http.Response, err error)
PostWithContext wraps the http.Get with circuit breaker and context
func (*CircuitBreaker) RoundTrip ¶
RoundTrip executes a single HTTP transaction, returning a Response for the provided Request. It wraps the standard http tranport method with circuit breaker
func (*CircuitBreaker) String ¶
func (cb *CircuitBreaker) String() string
type DefaultFailureDetector ¶
type DefaultFailureDetector struct{}
DefaultFailureDetector implements default failure detector behavior.
type FailureDetector ¶
FailureDetector defines the failure detector interface. Detector should decide if request result failed.
type Recoverer ¶
type Recoverer interface {
// Test receives the result of the request (failed or not)
// and returns True if recoverer decides that circuit breaker should close
Test(failure bool) bool
// Reset called when circuit breaker switched to Half-Open state
Reset()
}
Recoverer describes the interface to recover the circuit breaker
Circuir breaker in Half-Open state will test every request result with recoverer and will switch to Closed state it recoverer Test method returns true
type RecovererConseqSuccess ¶
type RecovererConseqSuccess struct {
// Threshold specifies how many consecutive successes should pass to trigger the state
Threshold int32
// contains filtered or unexported fields
}
RecovererConseqSuccess implements simple circuit breaker recoverer. It counts consecutive successfil results and triggers when counter reaches the threshold.
func (*RecovererConseqSuccess) Reset ¶
func (cs *RecovererConseqSuccess) Reset()
Reset resets the success counter
func (*RecovererConseqSuccess) Test ¶
func (cs *RecovererConseqSuccess) Test(failure bool) bool
Test returns True when number of consecutive successes reached the threshold
type Trigger ¶
type Trigger interface {
// Test receives the result of the request (failed or not)
// and returns True if trigger decides that circuit breaker should open
Test(failure bool) bool
// Reset called when circuit breaker switched back to Closed state
Reset()
}
Trigger describes the interface to trigger the opening of the circuit breaker.
Circuit breaker in Closed state will test every request result with trigger and will switch to Open state if trigger Test method returns true
type TriggerConseqFailure ¶
type TriggerConseqFailure struct {
// Threshold specifies how many consecutive failures should pass to trigger the state
Threshold int32
// contains filtered or unexported fields
}
TriggerConseqFailure implements simple circuit breaker trigger. It counts consecutive failures and triggers when counter reaches the threshold.
func (*TriggerConseqFailure) Reset ¶
func (cf *TriggerConseqFailure) Reset()
Reset resets the failure counter
func (*TriggerConseqFailure) Test ¶
func (cf *TriggerConseqFailure) Test(failure bool) bool
Test returns True when number of consecutive failures reached the threshold