1
Fork 0
mirror of https://github.com/caddyserver/caddy.git synced 2024-12-16 21:56:40 -05:00

reverse_proxy: CB docs; rename type -> factor (#2986)

* v2: add documentation for circuit breaker config and "random selection" load balancing policy

* v2: rename circuit breaker config inline key from `type` to `breaker` to avoid json key clash between the `circuit_breaker` type and the `type` field of the generic circuit breaker Config struct used by circuit breaking implementations

* v2: restore the circuit breaker inline key to `type` and rename the name circuit breaker config field from `Type` to `Factor`
This commit is contained in:
Mohammed Al Sahaf 2020-01-19 04:42:56 +03:00 committed by Matt Holt
parent 372540f0ee
commit 2bfaf8e896
2 changed files with 24 additions and 16 deletions

View file

@ -31,7 +31,7 @@ func init() {
// for requests within this process over a sliding time window. // for requests within this process over a sliding time window.
type localCircuitBreaker struct { type localCircuitBreaker struct {
tripped int32 tripped int32
cbType int32 cbFactor int32
threshold float64 threshold float64
metrics *memmetrics.RTMetrics metrics *memmetrics.RTMetrics
tripTime time.Duration tripTime time.Duration
@ -48,7 +48,7 @@ func (localCircuitBreaker) CaddyModule() caddy.ModuleInfo {
// Provision sets up a configured circuit breaker. // Provision sets up a configured circuit breaker.
func (c *localCircuitBreaker) Provision(ctx caddy.Context) error { func (c *localCircuitBreaker) Provision(ctx caddy.Context) error {
t, ok := typeCB[c.Type] f, ok := typeCB[c.Factor]
if !ok { if !ok {
return fmt.Errorf("type is not defined") return fmt.Errorf("type is not defined")
} }
@ -67,7 +67,7 @@ func (c *localCircuitBreaker) Provision(ctx caddy.Context) error {
return fmt.Errorf("cannot create new metrics: %v", err.Error()) return fmt.Errorf("cannot create new metrics: %v", err.Error())
} }
c.cbType = t c.cbFactor = f
c.tripTime = tw c.tripTime = tw
c.threshold = c.Threshold c.threshold = c.Threshold
c.metrics = mt c.metrics = mt
@ -92,13 +92,13 @@ func (c *localCircuitBreaker) RecordMetric(statusCode int, latency time.Duration
func (c *localCircuitBreaker) checkAndSet() { func (c *localCircuitBreaker) checkAndSet() {
var isTripped bool var isTripped bool
switch c.cbType { switch c.cbFactor {
case typeErrorRatio: case factorErrorRatio:
// check if amount of network errors exceed threshold over sliding window, threshold for comparison should be < 1.0 i.e. .5 = 50th percentile // check if amount of network errors exceed threshold over sliding window, threshold for comparison should be < 1.0 i.e. .5 = 50th percentile
if c.metrics.NetworkErrorRatio() > c.threshold { if c.metrics.NetworkErrorRatio() > c.threshold {
isTripped = true isTripped = true
} }
case typeLatency: case factorLatency:
// check if threshold in milliseconds is reached and trip // check if threshold in milliseconds is reached and trip
hist, err := c.metrics.LatencyHistogram() hist, err := c.metrics.LatencyHistogram()
if err != nil { if err != nil {
@ -109,7 +109,7 @@ func (c *localCircuitBreaker) checkAndSet() {
if l.Nanoseconds()/int64(time.Millisecond) > int64(c.threshold) { if l.Nanoseconds()/int64(time.Millisecond) > int64(c.threshold) {
isTripped = true isTripped = true
} }
case typeStatusCodeRatio: case factorStatusCodeRatio:
// check ratio of error status codes of sliding window, threshold for comparison should be < 1.0 i.e. .5 = 50th percentile // check ratio of error status codes of sliding window, threshold for comparison should be < 1.0 i.e. .5 = 50th percentile
if c.metrics.ResponseCodeRatio(500, 600, 0, 600) > c.threshold { if c.metrics.ResponseCodeRatio(500, 600, 0, 600) > c.threshold {
isTripped = true isTripped = true
@ -130,23 +130,28 @@ func (c *localCircuitBreaker) checkAndSet() {
// Config represents the configuration of a circuit breaker. // Config represents the configuration of a circuit breaker.
type Config struct { type Config struct {
// The threshold over sliding window that would trip the circuit breaker
Threshold float64 `json:"threshold"` Threshold float64 `json:"threshold"`
Type string `json:"type"` // Possible values: latency, error_ratio, and status_ratio. It
TripTime string `json:"trip_time"` // defaults to latency.
Factor string `json:"factor"`
// How long to wait after the circuit is tripped before allowing operations to resume.
// The default is 5s.
TripTime string `json:"trip_time"`
} }
const ( const (
typeLatency = iota + 1 factorLatency = iota + 1
typeErrorRatio factorErrorRatio
typeStatusCodeRatio factorStatusCodeRatio
defaultTripTime = "5s" defaultTripTime = "5s"
) )
var ( var (
// typeCB handles converting a Config Type value to the internal circuit breaker types. // typeCB handles converting a Config Factor value to the internal circuit breaker types.
typeCB = map[string]int32{ typeCB = map[string]int32{
"latency": typeLatency, "latency": factorLatency,
"error_ratio": typeErrorRatio, "error_ratio": factorErrorRatio,
"status_ratio": typeStatusCodeRatio, "status_ratio": factorStatusCodeRatio,
} }
) )

View file

@ -78,6 +78,8 @@ func (r RandomSelection) Select(pool UpstreamPool, request *http.Request) *Upstr
// two or more available hosts at random, then // two or more available hosts at random, then
// chooses the one with the least load. // chooses the one with the least load.
type RandomChoiceSelection struct { type RandomChoiceSelection struct {
// The size of the sub-pool created from the larger upstream pool. The default value
// is 2 and the maximum at selection time is the size of the upstream pool.
Choose int `json:"choose,omitempty"` Choose int `json:"choose,omitempty"`
} }
@ -283,6 +285,7 @@ func (URIHashSelection) Select(pool UpstreamPool, req *http.Request) *Upstream {
// HeaderHashSelection is a policy that selects // HeaderHashSelection is a policy that selects
// a host based on a given request header. // a host based on a given request header.
type HeaderHashSelection struct { type HeaderHashSelection struct {
// The HTTP header field whose value is to be hashed and used for upstream selection.
Field string `json:"field,omitempty"` Field string `json:"field,omitempty"`
} }