Send 'Retry-After' to comply with RFC6585.
This commit is contained in:
parent
027093a5a5
commit
8d75aba7eb
29 changed files with 435 additions and 172 deletions
40
vendor/github.com/vulcand/oxy/cbreaker/cbreaker.go
generated
vendored
40
vendor/github.com/vulcand/oxy/cbreaker/cbreaker.go
generated
vendored
|
@ -3,7 +3,7 @@
|
|||
// Vulcan circuit breaker watches the error condtion to match
|
||||
// after which it activates the fallback scenario, e.g. returns the response code
|
||||
// or redirects the request to another location
|
||||
|
||||
//
|
||||
// Circuit breakers start in the Standby state first, observing responses and watching location metrics.
|
||||
//
|
||||
// Once the Circuit breaker condition is met, it enters the "Tripped" state, where it activates fallback scenario
|
||||
|
@ -31,9 +31,8 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/mailgun/timetools"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/vulcand/oxy/memmetrics"
|
||||
"github.com/vulcand/oxy/utils"
|
||||
)
|
||||
|
@ -63,6 +62,8 @@ type CircuitBreaker struct {
|
|||
next http.Handler
|
||||
|
||||
clock timetools.TimeProvider
|
||||
|
||||
log *log.Logger
|
||||
}
|
||||
|
||||
// New creates a new CircuitBreaker middleware
|
||||
|
@ -76,6 +77,7 @@ func New(next http.Handler, expression string, options ...CircuitBreakerOption)
|
|||
fallbackDuration: defaultFallbackDuration,
|
||||
recoveryDuration: defaultRecoveryDuration,
|
||||
fallback: defaultFallback,
|
||||
log: log.StandardLogger(),
|
||||
}
|
||||
|
||||
for _, s := range options {
|
||||
|
@ -99,9 +101,19 @@ func New(next http.Handler, expression string, options ...CircuitBreakerOption)
|
|||
return cb, nil
|
||||
}
|
||||
|
||||
// Logger defines the logger the circuit breaker will use.
|
||||
//
|
||||
// It defaults to logrus.StandardLogger(), the global logger used by logrus.
|
||||
func Logger(l *log.Logger) CircuitBreakerOption {
|
||||
return func(c *CircuitBreaker) error {
|
||||
c.log = l
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CircuitBreaker) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
if log.GetLevel() >= log.DebugLevel {
|
||||
logEntry := log.WithField("Request", utils.DumpHttpRequest(req))
|
||||
if c.log.Level >= log.DebugLevel {
|
||||
logEntry := c.log.WithField("Request", utils.DumpHttpRequest(req))
|
||||
logEntry.Debug("vulcand/oxy/circuitbreaker: begin ServeHttp on request")
|
||||
defer logEntry.Debug("vulcand/oxy/circuitbreaker: completed ServeHttp on request")
|
||||
}
|
||||
|
@ -112,6 +124,7 @@ func (c *CircuitBreaker) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
c.serve(w, req)
|
||||
}
|
||||
|
||||
// Wrap sets the next handler to be called by circuit breaker handler.
|
||||
func (c *CircuitBreaker) Wrap(next http.Handler) {
|
||||
c.next = next
|
||||
}
|
||||
|
@ -126,7 +139,7 @@ func (c *CircuitBreaker) activateFallback(w http.ResponseWriter, req *http.Reque
|
|||
c.m.Lock()
|
||||
defer c.m.Unlock()
|
||||
|
||||
log.Warnf("%v is in error state", c)
|
||||
c.log.Warnf("%v is in error state", c)
|
||||
|
||||
switch c.state {
|
||||
case stateStandby:
|
||||
|
@ -156,7 +169,7 @@ func (c *CircuitBreaker) activateFallback(w http.ResponseWriter, req *http.Reque
|
|||
|
||||
func (c *CircuitBreaker) serve(w http.ResponseWriter, req *http.Request) {
|
||||
start := c.clock.UtcNow()
|
||||
p := utils.NewProxyWriter(w)
|
||||
p := utils.NewProxyWriterWithLogger(w, c.log)
|
||||
|
||||
c.next.ServeHTTP(p, req)
|
||||
|
||||
|
@ -191,13 +204,13 @@ func (c *CircuitBreaker) exec(s SideEffect) {
|
|||
}
|
||||
go func() {
|
||||
if err := s.Exec(); err != nil {
|
||||
log.Errorf("%v side effect failure: %v", c, err)
|
||||
c.log.Errorf("%v side effect failure: %v", c, err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (c *CircuitBreaker) setState(new cbState, until time.Time) {
|
||||
log.Debugf("%v setting state to %v, until %v", c, new, until)
|
||||
c.log.Debugf("%v setting state to %v, until %v", c, new, until)
|
||||
c.state = new
|
||||
c.until = until
|
||||
switch new {
|
||||
|
@ -230,7 +243,7 @@ func (c *CircuitBreaker) checkAndSet() {
|
|||
c.lastCheck = c.clock.UtcNow().Add(c.checkPeriod)
|
||||
|
||||
if c.state == stateTripped {
|
||||
log.Debugf("%v skip set tripped", c)
|
||||
c.log.Debugf("%v skip set tripped", c)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -244,7 +257,7 @@ func (c *CircuitBreaker) checkAndSet() {
|
|||
|
||||
func (c *CircuitBreaker) setRecovering() {
|
||||
c.setState(stateRecovering, c.clock.UtcNow().Add(c.recoveryDuration))
|
||||
c.rc = newRatioController(c.clock, c.recoveryDuration)
|
||||
c.rc = newRatioController(c.clock, c.recoveryDuration, c.log)
|
||||
}
|
||||
|
||||
// CircuitBreakerOption represents an option you can pass to New.
|
||||
|
@ -296,7 +309,7 @@ func OnTripped(s SideEffect) CircuitBreakerOption {
|
|||
}
|
||||
}
|
||||
|
||||
// OnTripped sets a SideEffect to run when entering the Standby state.
|
||||
// OnStandby sets a SideEffect to run when entering the Standby state.
|
||||
// Only one SideEffect can be set for this hook.
|
||||
func OnStandby(s SideEffect) CircuitBreakerOption {
|
||||
return func(c *CircuitBreaker) error {
|
||||
|
@ -346,8 +359,7 @@ const (
|
|||
|
||||
var defaultFallback = &fallback{}
|
||||
|
||||
type fallback struct {
|
||||
}
|
||||
type fallback struct{}
|
||||
|
||||
func (f *fallback) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue