circuitbreaker

package module
v0.0.0-...-edf747f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 6, 2021 License: MIT Imports: 8 Imported by: 0

README

CircuitBreaker

Package circuitbreaker implements CircuitBreaker pattern for http requests.

See https://docs.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker

Package provides light-weight and extendable implementation, fully compatible with standard HTTP Go library.

To get package documentation use standard godoc tool:

godoc

and open package documentation page: http://localhost:6060/pkg/github.com/vasmik/circuitbreaker/

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

Examples

Constants

This section is empty.

Variables

View Source
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.

View Source
var DefaultRecoverer = &RecovererConseqSuccess{Threshold: 5}

DefaultRecoverer used if no recoverer spacified for circuit breaker instance

View Source
var DefaultTimeout = 10 * time.Second

DefaultTimeout is the default value for the Open state time

View Source
var DefaultTimeoutJitter = 300 * time.Millisecond

DefaultTimeoutJitter is default value for the jitter to distribute the time for cliens get back to full consumption power

View Source
var DefaultTrigger = &TriggerConseqFailure{Threshold: 5}

DefaultTrigger used if no trigger specified for circuit breaker instance

View Source
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

func (cb *CircuitBreaker) RoundTrip(req *http.Request) (*http.Response, error)

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.

func (*DefaultFailureDetector) IsFailure

func (d *DefaultFailureDetector) IsFailure(res *http.Response, err error) bool

IsFailure returns True in case of 5xx response status code or any error except context cancelation.

type FailureDetector

type FailureDetector interface {
	IsFailure(res *http.Response, err error) bool
}

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 State

type State int

State type to indicate CircuitBreaker state

var (
	StateClosed   State = 0
	StateOpen     State = 1
	StateHalfOpen State = 2
)

State values

func (State) String

func (s State) String() string

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

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL