Pingora Load Balancing utilities
This crate provides common service discovery, health check and load balancing algorithms for proxies to use.
Grouped selector internals
In LoadBalancerGroup<S>, S is the selector algorithm and its built data,
such as a Ketama ring. The other types manage its configuration, rebuilding,
publication, and lifetime.
LoadBalancerGroup<S>
|-- BackendView (Backends)
| |-- ServiceDiscovery
| `-- Arc<HealthRegistry>
|-- SelectorRebuildGate
|-- SelectorRebuildCancellation
`-- SelectorSlot<S> x N
|-- config
|-- SelectorRebuildState
| `-- pending SelectorRebuildRequest
`-- ArcSwap<PublishedSelector<S>>
|-- Arc<S>
|-- readiness snapshot
`-- SelectorReleaseGuard
`-- SelectorReleaseSignal
Shared mode:
HealthCheckService ---> Arc<HealthRegistry> <--- other BackendViews
The main roles are:
Backends, also namedBackendView, owns discovered membership, enablement, health references, and the membership generation. Each published group selector owns the readiness snapshot for its generation, so older selectors keep serving their own snapshot.HealthRegistryreconciles the targets contributed by its views and owns one health state and probe target per backend equivalence key.HealthCheckServiceruns one active health-check loop for a shared registry. Views with private registries are checked by their load balancer.SelectorSlot<S>owns one selector configuration, its published selector, generation, pending work, timings, and counters.SelectorRebuildRequestcontains the backend membership, its readiness snapshot, and generation to build.SelectorRebuildStatetracks the active rebuild task and newest pending request.SelectorRebuildTaskGuardclears the running state and restores an in-flight request if the task exits unexpectedly.SelectorRebuildCancellationstops rebuild tasks when the group is dropped.PublishedSelector<S>pairs the selector exposed to requests with the readiness snapshot for its generation and its lifetime tracking.SelectorReleaseGuardandSelectorReleaseSignalnotify the gate after a replaced selector and all its readers are gone.SelectorRebuildGateallows one build at a time and prevents another build while an old selector is still being destroyed.
Discovery and shared-health flow
LoadBalancerGroup<S>asks itsBackendViewto update.- The view's
ServiceDiscoveryreturns its currentBackendmembership and enablement. BackendViewpublishes that membership and updates its contribution toHealthRegistry.HealthRegistryreconciles the targets from all of its views.- In shared mode,
HealthCheckServiceprobes each registry target once. - The resulting health state is visible through every contributing view.
- Each view applies its own membership and enablement. Each rebuilt group selector is published with the readiness snapshot for its generation.
Selector rebuild flow
Backendsadvances the membership generation and produces an indivisible membership and readiness update bundle.LoadBalancerGroup<S>schedules each selector rebuild from that bundle.SelectorRebuildStatekeeps one active rebuild and coalesces newer work into its pending request.SelectorRebuildTaskGuardtracks the in-flight request while the task acquiresSelectorRebuildGate.- The task builds the selector
Sfrom the request's backend snapshot. - A new
PublishedSelector<S>is stored in the slot'sArcSwap, replacing the old published selector atomically. - The slot publishes its selector generation and can process its next pending request.
Request flow
LoadBalancerGroup<S>::selectloads aPublishedSelector<S>from the chosenSelectorSlot<S>.- That published selector snapshot is held for the whole selection while it yields ordered backend candidates.
- The published selector's own readiness snapshot answers enablement and health for each candidate.
- The first accepted backend is returned; otherwise selection returns
None. - Replacing the selector does not affect this request's iterator.
- When the final reader releases the old
PublishedSelector<S>, itsSelectorReleaseGuardupdatesSelectorReleaseSignal. SelectorRebuildGateobserves that signal and permits the next build.
Cancellation flow
- Dropping
LoadBalancerGroup<S>triggersSelectorRebuildCancellation. - A task waiting for
SelectorRebuildGateexits without removing the old selector'sSelectorReleaseSignal. SelectorRebuildTaskGuardrestores an in-flightSelectorRebuildRequestunless a newer request already replaced it.- A built but unpublished selector is destroyed on a blocking worker.
- That destruction retains the gate permit, so another group cannot build at the same time.
- The task guard clears the slot's running state and notifies waiters.
- After destruction completes, the gate permit is released.