overload

package
v1.4.1 Latest Latest
Warning

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

Go to latest
Published: May 3, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package overload is a 5-stage CPU degradation ladder driven by observe.Collector.

A background polling goroutine samples collector.Snapshot().CPUUtilization every [Config.PollInterval] and transitions the stage atomically. Hot-path handlers read the stage via a single atomic load — no locks, no map lookups — so the Normal path adds only a few nanoseconds of overhead.

Stages (thresholds configurable, hysteresis applied to downward transitions):

Normal       — pass through unchanged
Expand       — signal best-effort worker widening; pass through
Reap         — opt-in runtime.GC() then pass through
Reorder      — low-priority requests return 503; others pass
Backpressure — low-priority requests sleep BackpressureDelay; others
               return 503; exempt pass through
Reject       — all non-exempt requests return 503 + Retry-After

Priority is application-defined via [Config.PriorityFunc]. Without it, Reorder passes everything and Backpressure delays everything.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func New

func New(config ...Config) celeris.HandlerFunc

New returns an overload middleware that uses the configured [Config.CollectorProvider] to sample CPU. A background goroutine is started; cancel it via [Config.StopContext] or use NewWithController for explicit control.

Types

type Config

type Config struct {
	// CollectorProvider returns the [observe.Collector] from which
	// CPU utilization is sampled. Required.
	CollectorProvider func() *observe.Collector

	// Thresholds sets the per-stage CPU fractions. Zero-valued fields
	// fall back to the defaults documented on [Thresholds].
	Thresholds Thresholds

	// DepthThresholds sets the per-stage in-flight request count that
	// escalates the driver. Optional; zero-valued fields are ignored.
	// See [DepthThresholds] for guidance.
	DepthThresholds DepthThresholds

	// LatencyThresholds sets the per-stage EMA tail-latency target that
	// escalates the driver. Optional; zero-valued fields are ignored.
	LatencyThresholds LatencyThresholds

	// LatencyEMAAlpha is the smoothing factor for the in-flight latency
	// EMA. 0..1 range; higher weights recent samples more aggressively.
	// Default: 0.1 (10% weight to current sample, 90% to history).
	LatencyEMAAlpha float64

	// PollInterval is how often the background goroutine samples CPU
	// and updates the stage. Default: 1 second.
	PollInterval time.Duration

	// ExemptPaths are request paths that never get degraded.
	ExemptPaths []string

	// ExemptFunc, when non-nil, short-circuits the degradation logic
	// for requests where it returns true.
	ExemptFunc func(*celeris.Context) bool

	// PriorityFunc classifies request priority for Reorder and
	// Backpressure stages. Higher values win. When nil, all requests
	// share the same priority (0) so Reorder passes everything and
	// Backpressure delays everything.
	PriorityFunc func(*celeris.Context) int

	// PriorityThreshold is the cutoff below which requests are rejected
	// at StageReorder and delayed/rejected at StageBackpressure.
	// Default: 0 (priority < 0 is "low").
	PriorityThreshold int

	// BackpressureDelay is the artificial latency added at
	// StageBackpressure for non-exempt low-priority requests.
	// Default: 50 ms.
	BackpressureDelay time.Duration

	// BackpressureStatus is the status code returned at StageBackpressure
	// for non-delayable requests. Default: 503.
	BackpressureStatus int

	// RejectStatus is the status code returned at StageReject.
	// Default: 503.
	RejectStatus int

	// RetryAfter is the Retry-After header value accompanying 503s.
	// Default: 5 seconds.
	RetryAfter time.Duration

	// EnableReap opts into calling runtime.GC() at StageReap. Default:
	// false. Forced GC can hurt tail latency; enable only when you
	// can measure the effect.
	EnableReap bool

	// ReapAggressiveness: 1=GC hint, 2=GC + encourage pool drain.
	// Default: 1.
	ReapAggressiveness int

	// Skip defines a function to skip this middleware for certain
	// requests (bypasses all stage logic).
	Skip func(*celeris.Context) bool

	// SkipPaths lists paths to skip entirely.
	SkipPaths []string

	// StopContext, when cancelled, stops the background sampling
	// goroutine. Default: context.Background (never cancels).
	StopContext context.Context
}

Config defines the overload middleware configuration.

Example

ExampleConfig — the middleware needs a [Config.CollectorProvider] to sample CPU/queue/latency signals. A celeris.Server's observe.Collector is the typical source; any function returning a `*observe.Collector` works.

In production wire it as `app.Use(overload.New(cfg))` after the server is constructed and its collector is reachable.

package main

import (
	"github.com/goceleris/celeris/middleware/overload"
	"github.com/goceleris/celeris/observe"
)

func main() {
	_ = overload.Config{
		CollectorProvider: func() *observe.Collector { return nil },
	}
}

type Controller

type Controller struct {
	// contains filtered or unexported fields
}

Controller exposes runtime introspection and control of a running overload middleware instance.

func NewWithController

func NewWithController(config ...Config) (celeris.HandlerFunc, *Controller)

NewWithController is like New but also returns a Controller for querying the current stage and stopping the poll goroutine.

func (*Controller) CPUSample

func (c *Controller) CPUSample() float64

CPUSample returns the CPU utilization (0..1) from the last completed poll tick. Returns -1 if no sample has been taken yet.

func (*Controller) InFlight

func (c *Controller) InFlight() int32

InFlight returns the current in-flight request count observed by the middleware. Not affected by SkipPaths / ExemptPaths (they never touch the counter).

func (*Controller) LatencyEMA

func (c *Controller) LatencyEMA() time.Duration

LatencyEMA returns the current smoothed (EMA) tail latency across observed non-exempt requests. Zero if no requests have completed yet.

func (*Controller) Stage

func (c *Controller) Stage() Stage

Stage returns the current stage.

func (*Controller) Stop

func (c *Controller) Stop()

Stop cancels the background sampling goroutine. Safe to call multiple times. After Stop the stage stays frozen at whatever value it last observed.

type DepthThresholds

type DepthThresholds struct {
	Expand       int32 // default 0 (disabled)
	Reap         int32 // default 0 (disabled)
	Reorder      int32 // default 0 (disabled)
	Backpressure int32 // default 0 (disabled)
	Reject       int32 // default 0 (disabled)
	Hysteresis   int32 // default 0 (no hysteresis on depth)
}

DepthThresholds defines the per-stage in-flight request count that escalates the driver independent of CPU. Zero-valued fields disable the depth signal for that stage (CPU-only). Each threshold is an absolute count — if the middleware observes N >= threshold in-flight requests, the effective stage is at least that one.

Depth is the most reliable overload signal when handlers block on upstream I/O: CPU stays low while requests queue up. Typical choice: Reorder = 2×NumWorkers, Backpressure = 4×NumWorkers, Reject = 8×NumWorkers.

type LatencyThresholds

type LatencyThresholds struct {
	Expand       time.Duration // default 0 (disabled)
	Reap         time.Duration // default 0 (disabled)
	Reorder      time.Duration // default 0 (disabled)
	Backpressure time.Duration // default 0 (disabled)
	Reject       time.Duration // default 0 (disabled)
	Hysteresis   time.Duration // default 0 (no hysteresis on latency)
}

LatencyThresholds defines the per-stage EMA tail-latency target that escalates the driver independent of CPU or depth. When the smoothed latency EMA exceeds a threshold, the effective stage is at least that one. Zero-valued fields disable the latency signal for that stage.

Latency is the right signal for SLO-aware degradation: at fixed CPU and fixed load, a sudden jump in latency usually means an upstream has slowed down — applying backpressure early preserves overall SLO.

type Stage

type Stage int32

Stage identifies one of the five CPU-pressure stages the driver can occupy. Stages rise as CPU utilization crosses upward thresholds and fall after CPU drops below (upper - Hysteresis).

const (
	StageNormal       Stage = iota // 0: no action
	StageExpand                    // 1: widen engine workers (best-effort)
	StageReap                      // 2: opt-in runtime.GC()
	StageReorder                   // 3: priority-gated handling
	StageBackpressure              // 4: delay low-priority; 503 others
	StageReject                    // 5: 503 all non-exempt
)

Stage values.

func (Stage) String

func (s Stage) String() string

String returns the stage name for diagnostics.

type Thresholds

type Thresholds struct {
	Expand       float64 // default 0.70
	Reap         float64 // default 0.80
	Reorder      float64 // default 0.85
	Backpressure float64 // default 0.90
	Reject       float64 // default 0.95
	Hysteresis   float64 // default 0.05
}

Thresholds defines the upward transition CPU fractions (0.0..1.0). Each field is the lower bound for entering that stage. The downward transition threshold is (upper - Hysteresis).

Jump to

Keyboard shortcuts

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