Documentation
¶
Overview ¶
Package loadbalancer is the product-level load balancer model layered on the embedded Caddy reverse_proxy upstream pool (internal/ingress).
Index ¶
- Constants
- func Algorithms() []string
- func DefaultCheckTimeout() time.Duration
- func EffectiveWeights(cfg Config, ups []Upstream, firstSeen map[string]time.Time, now time.Time) []int
- func ParseDuration(s string) time.Duration
- func ParseUpstreamReplica(service, id string) (int, bool)
- func UpstreamID(service string, replica int) string
- func ValidAdminState(s string) bool
- type ActiveHealth
- type CaddyAdminStats
- type CheckGate
- type CheckOutcome
- type CheckRecord
- type CheckResult
- type Config
- type HTTPProber
- type HistoryConfig
- type Observation
- type PassiveHealth
- type ProbeResult
- type Prober
- type RateLimit
- type Registry
- func (r *Registry) FirstSeen(service string, ids []string, now time.Time) map[string]time.Time
- func (r *Registry) Get(service string) (Observation, bool)
- func (r *Registry) History(st Status, limit int) []UpstreamHistory
- func (r *Registry) List() []Observation
- func (r *Registry) Record(o Observation)
- func (r *Registry) RecordStatus(st *Status)
- func (r *Registry) Retain(keep map[string]bool)
- type Retries
- type SeriesPoint
- type SeriesSet
- type Stats
- type StatsSource
- type Status
- type Transition
- type Upstream
- type UpstreamHistory
- type UpstreamObservation
- type UpstreamStatus
- type UpstreamTLS
- type ValidationError
Constants ¶
const ( AlgoRoundRobin = "round_robin" AlgoLeastConn = "least_conn" AlgoIPHash = "ip_hash" AlgoURIHash = "uri_hash" AlgoCookie = "cookie" AlgoWeighted = "weighted" )
Algorithms selectable in Config.Algorithm.
const ( StateHealthy = "healthy" StateUnhealthy = "unhealthy" StateDraining = "draining" StateUnknown = "unknown" StateDisabled = "disabled" )
Upstream states reported by BuildStatus.
const ( AdminActive = "active" AdminDraining = "draining" AdminDisabled = "disabled" )
Operator-set admin states for one upstream.
const MaxWeight = 100
MaxWeight caps a per-upstream weight.
Variables ¶
This section is empty.
Functions ¶
func Algorithms ¶
func Algorithms() []string
Algorithms lists every valid algorithm in display order.
func DefaultCheckTimeout ¶
DefaultCheckTimeout is the probe timeout when no active health check is configured, overridable with APP_LB_CHECK_TIMEOUT.
func EffectiveWeights ¶
func EffectiveWeights(cfg Config, ups []Upstream, firstSeen map[string]time.Time, now time.Time) []int
EffectiveWeights returns one weight per upstream. When slow start is set, an upstream first seen less than SlowStart ago ramps linearly from 1 to its configured weight. Only meaningful for the weighted algorithm.
func ParseDuration ¶
ParseDuration parses a validated duration string, returning zero for empty.
func ParseUpstreamReplica ¶
ParseUpstreamReplica extracts the replica index from an ID built by UpstreamID for service.
func UpstreamID ¶
UpstreamID builds the stable ID for a service replica.
func ValidAdminState ¶
ValidAdminState reports whether s is one of the admin states.
Types ¶
type ActiveHealth ¶
type ActiveHealth struct {
Path string `yaml:"path" json:"path"`
Interval string `yaml:"interval,omitempty" json:"interval,omitempty"`
Timeout string `yaml:"timeout,omitempty" json:"timeout,omitempty"`
Passes int `yaml:"passes,omitempty" json:"passes,omitempty"`
Fails int `yaml:"fails,omitempty" json:"fails,omitempty"`
ExpectStatus int `yaml:"expect_status,omitempty" json:"expect_status,omitempty"`
}
ActiveHealth probes each upstream on an interval.
type CaddyAdminStats ¶
type CaddyAdminStats struct {
// Addr is the admin listen address, e.g. "localhost:2019".
Addr string
Client *http.Client
}
CaddyAdminStats reads counters from Caddy's admin /reverse_proxy/upstreams.
func (CaddyAdminStats) UpstreamStats ¶
UpstreamStats implements StatsSource.
type CheckGate ¶
type CheckGate struct {
// contains filtered or unexported fields
}
CheckGate rate limits check-now per service.
func CheckGateFromEnv ¶
func CheckGateFromEnv() *CheckGate
CheckGateFromEnv sizes the gate from APP_LB_CHECK_MIN_INTERVAL (default 2s).
func NewCheckGate ¶
NewCheckGate returns a gate allowing one check per service per min.
type CheckOutcome ¶
type CheckOutcome struct {
Results []CheckResult
// Note is set when the balancer has no active health check configured.
Note string
Status Status
}
CheckOutcome is the result of CheckNow.
func CheckNow ¶
func CheckNow(ctx context.Context, reg *Registry, obs Observation, stats map[string]Stats, prober Prober) CheckOutcome
CheckNow probes every running upstream once, in parallel and bounded by the probe timeout, using the configured active health check (or GET / when none is set). It records the results into reg and returns them.
type CheckRecord ¶
type CheckRecord struct {
At time.Time `json:"at"`
OK bool `json:"ok"`
StatusCode int `json:"status_code"`
LatencyMs int64 `json:"latency_ms"`
Reason string `json:"reason"`
}
CheckRecord is one health probe outcome.
type CheckResult ¶
type CheckResult struct {
ID string `json:"id"`
Dial string `json:"dial"`
OK bool `json:"ok"`
StatusCode int `json:"status_code"`
LatencyMs int64 `json:"latency_ms"`
Reason string `json:"reason"`
}
CheckResult is one upstream's outcome from a check-now run.
type Config ¶
type Config struct {
Algorithm string `yaml:"algorithm,omitempty" json:"algorithm,omitempty"`
CookieName string `yaml:"cookie_name,omitempty" json:"cookie_name,omitempty"`
// Weights is indexed by replica number; missing entries default to 1.
Weights []int `yaml:"weights,omitempty" json:"weights,omitempty"`
ActiveHealth *ActiveHealth `yaml:"active_health,omitempty" json:"active_health,omitempty"`
PassiveHealth *PassiveHealth `yaml:"passive_health,omitempty" json:"passive_health,omitempty"`
Retries *Retries `yaml:"retries,omitempty" json:"retries,omitempty"`
SlowStart string `yaml:"slow_start,omitempty" json:"slow_start,omitempty"`
DrainTimeout string `yaml:"drain_timeout,omitempty" json:"drain_timeout,omitempty"`
RequestTimeout string `yaml:"request_timeout,omitempty" json:"request_timeout,omitempty"`
RateLimit *RateLimit `yaml:"rate_limit,omitempty" json:"rate_limit,omitempty"`
UpstreamTLS *UpstreamTLS `yaml:"upstream_tls,omitempty" json:"upstream_tls,omitempty"`
}
Config is one service's load balancer settings. A nil *Config means the service has no load balancer and keeps its single-upstream route.
func (*Config) EffectiveAlgorithm ¶
EffectiveAlgorithm returns the configured algorithm or the default.
type HTTPProber ¶
type HTTPProber struct{}
HTTPProber is the real Prober.
func (HTTPProber) Probe ¶
func (HTTPProber) Probe(ctx context.Context, dial, path string, upstreamTLS *UpstreamTLS, timeout time.Duration) ProbeResult
Probe implements Prober.
type HistoryConfig ¶
type HistoryConfig struct {
Checks int
Transitions int
SeriesStep time.Duration
SeriesWindow time.Duration
MaxAge time.Duration
}
HistoryConfig bounds the in-memory per-upstream history.
func HistoryConfigFromEnv ¶
func HistoryConfigFromEnv() HistoryConfig
HistoryConfigFromEnv reads the history bounds, falling back to defaults.
type Observation ¶
type Observation struct {
Service string `json:"service"`
Config Config `json:"config"`
Upstreams []UpstreamObservation `json:"upstreams"`
Reason string `json:"reason"`
Message string `json:"message"`
Ready bool `json:"ready"`
ObservedAt time.Time `json:"observed_at"`
}
Observation is the reconciler's last view of one service's balancer.
type PassiveHealth ¶
type PassiveHealth struct {
FailDuration string `yaml:"fail_duration,omitempty" json:"fail_duration,omitempty"`
MaxFails int `yaml:"max_fails,omitempty" json:"max_fails,omitempty"`
}
PassiveHealth marks an upstream down after failures seen on live traffic.
type ProbeResult ¶
type ProbeResult struct {
OK bool
StatusCode int
Latency time.Duration
Err string
CheckedAt time.Time
}
ProbeResult is one active health check outcome.
type Prober ¶
type Prober interface {
Probe(ctx context.Context, dial, path string, tlsCfg *UpstreamTLS, timeout time.Duration) ProbeResult
}
Prober runs an active health check against one upstream.
type RateLimit ¶
type RateLimit struct {
RPS int `yaml:"rps" json:"rps"`
Burst int `yaml:"burst,omitempty" json:"burst,omitempty"`
}
RateLimit caps requests per second per client address.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry shares reconciler observations with the API and telemetry.
func NewRegistry ¶
func NewRegistry() *Registry
NewRegistry returns an empty Registry with history sized from the environment.
func NewRegistryWithHistory ¶
func NewRegistryWithHistory(cfg HistoryConfig) *Registry
NewRegistryWithHistory returns an empty Registry with explicit history bounds.
func (*Registry) FirstSeen ¶
FirstSeen records the first time each upstream ID was seen for service and forgets IDs no longer present. The first call for a service treats every upstream as long-running so a process restart does not restart slow start.
func (*Registry) Get ¶
func (r *Registry) Get(service string) (Observation, bool)
Get returns the latest observation for service.
func (*Registry) History ¶
func (r *Registry) History(st Status, limit int) []UpstreamHistory
History returns the recorded history for every upstream in st, checks capped to limit (0 means the ring size).
func (*Registry) List ¶
func (r *Registry) List() []Observation
List returns every recorded observation.
func (*Registry) Record ¶
func (r *Registry) Record(o Observation)
Record stores the latest observation for a service.
func (*Registry) RecordStatus ¶
RecordStatus records st into the history (probe results, state transitions, sampled series) and fills each upstream's LastChangedAt. History is in memory and resets when the control plane restarts.
type Retries ¶
type Retries struct {
Count int `yaml:"count,omitempty" json:"count,omitempty"`
TryDuration string `yaml:"try_duration,omitempty" json:"try_duration,omitempty"`
TryInterval string `yaml:"try_interval,omitempty" json:"try_interval,omitempty"`
}
Retries controls how a failed request is retried on another upstream.
type SeriesPoint ¶
SeriesPoint is one sampled value.
type SeriesSet ¶
type SeriesSet struct {
Connections []SeriesPoint `json:"connections"`
LatencyMs []SeriesPoint `json:"latency_ms"`
Fails []SeriesPoint `json:"fails"`
}
SeriesSet is the short per-upstream sample series.
type StatsSource ¶
StatsSource reports live proxy counters keyed by dial address.
type Status ¶
type Status struct {
Service string `json:"service"`
Algorithm string `json:"algorithm"`
Ready bool `json:"ready"`
Reason string `json:"reason"`
Message string `json:"message"`
ObservedAt time.Time `json:"observed_at"`
Upstreams []UpstreamStatus `json:"upstreams"`
}
Status is the API view of one service's load balancer.
func BuildStatus ¶
func BuildStatus(ctx context.Context, obs Observation, stats map[string]Stats, prober Prober) Status
BuildStatus merges an observation with proxy counters and active probes. stats and prober may be nil.
type Transition ¶
type Transition struct {
At time.Time `json:"at"`
From string `json:"from"`
To string `json:"to"`
Reason string `json:"reason"`
}
Transition is one upstream state change.
type Upstream ¶
type Upstream struct {
// ID is stable across passes (service name plus replica index), used to
// track first-seen time for slow start.
ID string `json:"id"`
Dial string `json:"dial"`
Replica int `json:"replica"`
// NodeID is empty for the control plane's own node.
NodeID string `json:"node_id,omitempty"`
}
Upstream is one replica endpoint the balancer can send traffic to.
type UpstreamHistory ¶
type UpstreamHistory struct {
ID string `json:"id"`
Dial string `json:"dial"`
AdminState string `json:"admin_state"`
Checks []CheckRecord `json:"checks"`
Transitions []Transition `json:"transitions"`
Series SeriesSet `json:"series"`
}
UpstreamHistory is the recorded history of one upstream.
type UpstreamObservation ¶
type UpstreamObservation struct {
Upstream
Running bool `json:"running"`
// Draining marks a previous-release container kept in the pool while the
// new release is not ready yet.
Draining bool `json:"draining,omitempty"`
Weight int `json:"weight"`
Note string `json:"note,omitempty"`
// AdminState is the operator's choice; empty means active.
AdminState string `json:"admin_state,omitempty"`
}
UpstreamObservation is what the reconciler saw for one upstream.
func (UpstreamObservation) InPool ¶
func (u UpstreamObservation) InPool() bool
InPool reports whether the upstream may receive new connections.
type UpstreamStatus ¶
type UpstreamStatus struct {
ID string `json:"id"`
Dial string `json:"dial"`
NodeID string `json:"node_id,omitempty"`
Replica int `json:"replica"`
Weight int `json:"weight"`
State string `json:"state"`
Healthy bool `json:"healthy"`
ActiveConns int `json:"active_connections"`
Fails int `json:"fails"`
LastCheck *time.Time `json:"last_check,omitempty"`
LatencyMs int64 `json:"latency_ms,omitempty"`
Reason string `json:"reason,omitempty"`
AdminState string `json:"admin_state"`
// LastChangedAt is when State last changed, or when it was first observed.
LastChangedAt *time.Time `json:"last_changed_at,omitempty"`
// contains filtered or unexported fields
}
UpstreamStatus is the live view of one upstream.
type UpstreamTLS ¶
type UpstreamTLS struct {
InsecureSkipVerify bool `yaml:"insecure_skip_verify,omitempty" json:"insecure_skip_verify,omitempty"`
ServerName string `yaml:"server_name,omitempty" json:"server_name,omitempty"`
}
UpstreamTLS makes the proxy speak HTTPS to upstreams.
type ValidationError ¶
type ValidationError struct{ Problems []string }
ValidationError lists every problem found in a Config.
func (*ValidationError) Error ¶
func (e *ValidationError) Error() string