UpstreamLb

Struct UpstreamLb 

Source
pub struct UpstreamLb { /* private fields */ }
Expand description

A load balancer for one upstream: lock-free picks over an atomically swappable endpoint set. Share via Arc; cheap to read from any task.

Implementations§

Source§

impl UpstreamLb

Source

pub fn new( endpoints: &[Endpoint], algorithm: LoadBalancer, slow_start: Duration, ) -> Arc<Self>

Build a balancer with a fresh endpoint set (all slow-start clocks start now) and passive health DISABLED. See UpstreamLb::new_with_health.

Source

pub fn new_with_health( endpoints: &[Endpoint], algorithm: LoadBalancer, slow_start: Duration, health: Option<&PassiveHealth>, ) -> Arc<Self>

new with passive health (DW-012): when health is Some, every endpoint gets a fresh health tracker and picks skip ejected endpoints (all-ejected falls back to the full set; see choose). The config form is resolved via HealthParams::from_config; validation guarantees its bounds.

Source

pub fn new_with_health_and_events( endpoints: &[Endpoint], algorithm: LoadBalancer, slow_start: Duration, health: Option<&PassiveHealth>, events: Option<&UpstreamEmitter>, peak_ewma: Option<&PeakEwmaConfig>, locality: Option<&UpstreamLocality>, ) -> Arc<Self>

new_with_health with ejection/recovery events (DW-044): fresh trackers are created bound to events (an upstream-labeled emitter), so their ejection/recovery transitions emit onto the event bus. Carried trackers keep the binding they were built with. None behaves exactly like UpstreamLb::new_with_health. peak_ewma (DW-090) is the per-upstream tuning consulted only when algorithm == PeakEwma; None uses the built-in defaults. locality (DW-094, Ent) is the per-upstream locality-aware routing config; None disables locality filtering.

Source

pub fn rebuild( &self, endpoints: &[Endpoint], algorithm: LoadBalancer, slow_start: Duration, )

Hot-swap the endpoint set and/or algorithm (passive health disabled; see UpstreamLb::rebuild_with_health). Unchanged addresses keep their in-flight counters, WRR phase, slow-start entry instant, and health trackers; new addresses start fresh. Atomic; concurrent picks see either the old or the new set, never a mix.

Source

pub fn rebuild_with_health( &self, endpoints: &[Endpoint], algorithm: LoadBalancer, slow_start: Duration, health: Option<&PassiveHealth>, )

rebuild with passive health parameters for the new generation (DW-012). Unchanged addresses keep their LIVE trackers (streak and observation window survive the reload); the new parameters apply to NEW observations only. Health state is carried per address:port, exactly like in-flight counters; removed endpoints drop their trackers outright and re-added ones start healthy with no history.

Source

pub fn rebuild_with_health_and_events( &self, endpoints: &[Endpoint], algorithm: LoadBalancer, slow_start: Duration, health: Option<&PassiveHealth>, events: Option<&UpstreamEmitter>, peak_ewma: Option<&PeakEwmaConfig>, locality: Option<&UpstreamLocality>, )

rebuild_with_health with ejection/recovery events (DW-044): trackers created by THIS rebuild bind events; carried trackers keep their original binding (the emitter is per-dataplane and stable, so in practice the two agree). None behaves exactly like UpstreamLb::rebuild_with_health. peak_ewma (DW-090) is the per-upstream tuning consulted only when algorithm == PeakEwma; None uses the built-in defaults. locality (DW-094, Ent) is the per-upstream locality-aware routing config; None disables locality filtering for this generation.

Source

pub fn rebuild_with_resolved_health_and_events( &self, endpoints: &[Endpoint], algorithm: LoadBalancer, slow_start: Duration, health: Option<Arc<HealthParams>>, events: Option<&UpstreamEmitter>, peak_ewma: Option<&PeakEwmaConfig>, locality: Option<&UpstreamLocality>, )

DW-042: rebuild_with_health_and_events taking RESOLVED health parameters (Arc<HealthParams>) instead of the config form. The DNS discovery task reads the resolved parameters from the current LbState (via UpstreamLb::health_config) so a live endpoint-set swap uses the same health parameters as the initial build without re-resolving the config form. peak_ewma (DW-090) is the per-upstream tuning consulted only when algorithm == PeakEwma; None uses the built-in defaults. locality (DW-094, Ent) is the per-upstream locality-aware routing config; None disables locality filtering for this generation.

Source

pub fn now_ms(&self) -> u64

Current passive-health clock reading (Unix-epoch ms).

Source

pub fn set_health_clock(&self, clock: fn() -> u64)

Replace the passive-health clock (Unix-epoch milliseconds; must be cheap). Intended for tests and other time-controlled setups — the same injection pattern as the rate limiter’s clock (DW-004). Production code keeps the default system clock.

Source

pub fn fail_open_picks(&self) -> u64

Picks that served from the full endpoint set because every endpoint was ejected (fail-open). See choose.

Source

pub fn len(&self) -> usize

Number of endpoints in the current set.

Source

pub fn is_empty(&self) -> bool

Whether the current set is empty (only via unvalidated configs).

Source

pub fn algorithm(&self) -> LoadBalancer

DW-042: the load-balancing algorithm of the current state. The discovery task reads this so a live endpoint-set swap uses the same algorithm as the initial build.

Source

pub fn slow_start(&self) -> Duration

DW-042: the slow-start window of the current state. The discovery task reads this so a live endpoint-set swap applies the same slow-start ramp as the initial build.

Source

pub fn health_config(&self) -> Option<Arc<HealthParams>>

DW-042: the resolved passive-health parameters of the current state, if passive health is enabled. The discovery task reads this so a live endpoint-set swap creates health trackers with the same parameters as the initial build.

Source

pub fn peak_ewma_config(&self) -> Option<Arc<PeakEwmaConfig>>

DW-090: the resolved peak-EWMA config of the current state, if the algorithm is peak_ewma. The discovery task reads this so a live endpoint-set swap uses the same tuning (decay tau, initial cost) as the initial build.

Source

pub fn events(&self) -> Option<UpstreamEmitter>

DW-042: the upstream-scoped event emitter, if the balancer was built with one. The discovery task passes this to rebuild_with_health_and_events so new endpoints get event-bound health trackers.

Source

pub fn set_locality_context(&self, ctx: LocalityContext)

DW-094 (Ent): set the edge’s locality context (region/zone). Applied to every upstream’s balancer by the dataplane at startup (from env vars or edge labels). Read on every pick when the upstream has locality configured; ignored otherwise.

Source

pub fn locality_config(&self) -> Option<Arc<UpstreamLocality>>

DW-094 (Ent): the resolved locality-aware routing config for the current generation, if any. The discovery task reads this so a live endpoint-set swap preserves the locality config.

Source

pub fn endpoint(&self, idx: usize) -> Option<(String, u16)>

address:port of endpoint idx in the current set.

Source

pub fn health_targets(&self) -> Vec<(String, u16, Option<Arc<EndpointHealth>>)>

Every endpoint’s address:port and passive-health tracker in the current set, in state order. Trackers are present only when the generation carries passive health (DW-012). This is the ACTIVE health engine’s (DW-013) view: probe loops target a SPECIFIC endpoint and report into its live tracker, bypassing balancing. Single atomic state load, so address and tracker always correspond.

Source

pub fn inflight(&self, idx: usize) -> u64

Current in-flight count for endpoint idx.

Source

pub fn acquire_inflight(self: &Arc<Self>, idx: usize) -> Option<InflightGuard>

Increment endpoint idx’s in-flight counter; returns a guard that decrements it on drop. Used by the upstream handle around dispatch.

Source

pub fn record_latency(&self, idx: usize, duration: Duration)

Record an observed latency for endpoint idx (DW-090). Updates the endpoint’s peak-EWMA cost tracker using the Finagle formula:

  • w = exp(-td / tau) where td is the time since the last update and tau is the decay window (peak_ewma.decay_ms).
  • If rtt > cost (the new RTT exceeds the current cost), the cost is replaced outright (the “peak” — a slow response is remembered in full so the balancer degrades an outlier immediately).
  • Otherwise cost = cost * w + rtt * (1 - w) (the cost decays toward the new RTT).

No-op when the endpoint has no peak-EWMA tracker (the algorithm is not peak_ewma, or the index is out of range). Lock-free: the tracker’s cost_ns and stamp are atomics. The latency is recorded for ALL outcomes (success, error, timeout) since even a timeout is a latency signal.

Source

pub fn peak_ewma_cost(&self, idx: usize) -> Option<u64>

The current peak-EWMA cost (nanoseconds) for endpoint idx, or None when the endpoint has no tracker (the algorithm is not peak_ewma or the index is out of range). Test/diagnostic helper.

Source

pub fn pick(&self, key: Option<&str>) -> Option<usize>

Pick the endpoint index for one dispatch. key is the hash key (client IP) used by ip_hash; other algorithms ignore it. Lock-free.

Source

pub fn pick_endpoint(&self, key: Option<&str>) -> Option<(usize, String, u16)>

Single-load pick returning the index AND the endpoint’s address:port from the SAME state snapshot (no reload can interleave between pick and resolution). For dispatch paths that do not need an in-flight guard (e.g. TLS passthrough).

Source

pub fn pick_for_dispatch( self: &Arc<Self>, key: Option<&str>, ) -> Option<Dispatch>

Single-load pick + in-flight acquisition: the algorithm choice, the endpoint resolution, and the counter increment all happen against ONE ArcSwap snapshot, so a concurrent rebuild cannot detach the guard from the endpoint it counted (the guard pins that snapshot). Prefer this over separate pick/endpoint/acquire_inflight calls on any dispatch path.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> AnyExt for T
where T: Any + ?Sized,

§

fn downcast_ref<T>(this: &Self) -> Option<&T>
where T: Any,

Attempts to downcast this to T behind reference
§

fn downcast_mut<T>(this: &mut Self) -> Option<&mut T>
where T: Any,

Attempts to downcast this to T behind mutable reference
§

fn downcast_rc<T>(this: Rc<Self>) -> Result<Rc<T>, Rc<Self>>
where T: Any,

Attempts to downcast this to T behind Rc pointer
§

fn downcast_arc<T>(this: Arc<Self>) -> Result<Arc<T>, Arc<Self>>
where T: Any,

Attempts to downcast this to T behind Arc pointer
§

fn downcast_box<T>(this: Box<Self>) -> Result<Box<T>, Box<Self>>
where T: Any,

Attempts to downcast this to T behind Box pointer
§

fn downcast_move<T>(this: Self) -> Option<T>
where T: Any, Self: Sized,

Attempts to downcast owned Self to T, useful only in generic context as a workaround for specialization
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T, X> CoerceTo<T> for X
where T: CoerceFrom<X> + ?Sized,

§

fn coerce_rc_to(self: Rc<X>) -> Rc<T>

§

fn coerce_box_to(self: Box<X>) -> Box<T>

§

fn coerce_ref_to(&self) -> &T

§

fn coerce_mut_to(&mut self) -> &mut T

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<T> ServiceExt for T

§

fn map_response_body<F>(self, f: F) -> MapResponseBody<Self, F>
where Self: Sized,

Apply a transformation to the response body. Read more
§

fn trace_for_http(self) -> Trace<Self, SharedClassifier<ServerErrorsAsFailures>>
where Self: Sized,

High level tracing that classifies responses using HTTP status codes. Read more
§

fn trace_for_grpc(self) -> Trace<Self, SharedClassifier<GrpcErrorsAsFailures>>
where Self: Sized,

High level tracing that classifies responses using gRPC headers. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,