diff --git a/tower-balance/examples/demo.rs b/tower-balance/examples/demo.rs index de9845f..fce814a 100644 --- a/tower-balance/examples/demo.rs +++ b/tower-balance/examples/demo.rs @@ -61,13 +61,13 @@ fn main() { let exec = executor.clone(); let fut = future::lazy(move || { let d = gen_disco(exec.clone()); - let ll = lb::power_of_two_choices(lb::load::WithPendingRequests::new(d)); + let ll = lb::Balance::p2c(lb::load::WithPendingRequests::new(d)); run("P2C+LeastLoaded", ll, &exec) }); let exec = executor; let fut = fut.and_then(move |_| { - let rr = lb::round_robin(gen_disco(exec.clone())); + let rr = lb::Balance::round_robin(gen_disco(exec.clone())); run("RoundRobin", rr, &exec) }); diff --git a/tower-balance/src/lib.rs b/tower-balance/src/lib.rs index 6f6e60c..874ac83 100644 --- a/tower-balance/src/lib.rs +++ b/tower-balance/src/lib.rs @@ -13,6 +13,7 @@ extern crate tower_service; use futures::{Async, Future, Poll}; use indexmap::IndexMap; +use rand::{SeedableRng, rngs::SmallRng}; use std::{fmt, error}; use std::marker::PhantomData; use tower_discover::Discover; @@ -24,36 +25,6 @@ pub mod load; pub use choose::Choose; pub use load::Load; -/// Chooses services using the [Power of Two Choices][p2c]. -/// -/// This configuration is prefered when a load metric is known. -/// -/// As described in the [Finagle Guide][finagle]: -/// > The algorithm randomly picks two services from the set of ready endpoints and selects -/// > the least loaded of the two. By repeatedly using this strategy, we can expect a -/// > manageable upper bound on the maximum load of any server. -/// > -/// > The maximum load variance between any two servers is bound by `ln(ln(n))` where `n` -/// > is the number of servers in the cluster. -/// -/// [finagle]: https://twitter.github.io/finagle/guide/Clients.html#power-of-two-choices-p2c-least-loaded -/// [p2c]: http://www.eecs.harvard.edu/~michaelm/postscripts/handbook2001.pdf -pub fn power_of_two_choices(loaded: D) -> Balance -where - D: Discover, - D::Service: Load, - ::Metric: PartialOrd + fmt::Debug, -{ - Balance::new(loaded, choose::PowerOfTwoChoices::default()) -} - -/// Attempts to choose services sequentially. -/// -/// This configuration is prefered when no load metric is known. -pub fn round_robin(discover: D) -> Balance { - Balance::new(discover, choose::RoundRobin::default()) -} - /// Balances requests across a set of inner services. #[derive(Debug)] pub struct Balance { @@ -90,6 +61,52 @@ pub struct ResponseFuture(F, PhantomData); // ===== impl Balance ===== +impl Balance +where + D: Discover, + D::Service: Load, + ::Metric: PartialOrd + fmt::Debug, +{ + /// Chooses services using the [Power of Two Choices][p2c]. + /// + /// This configuration is prefered when a load metric is known. + /// + /// As described in the [Finagle Guide][finagle]: + /// + /// > The algorithm randomly picks two services from the set of ready endpoints and + /// > selects the least loaded of the two. By repeatedly using this strategy, we can + /// > expect a manageable upper bound on the maximum load of any server. + /// > + /// > The maximum load variance between any two servers is bound by `ln(ln(n))` where + /// > `n` is the number of servers in the cluster. + /// + /// [finagle]: https://twitter.github.io/finagle/guide/Clients.html#power-of-two-choices-p2c-least-loaded + /// [p2c]: http://www.eecs.harvard.edu/~michaelm/postscripts/handbook2001.pdf + pub fn p2c(discover: D) -> Self { + Self::new(discover, choose::PowerOfTwoChoices::default()) + } + + /// Initializes a P2C load balancer from the provided randomization source. + /// + /// This may be preferable when an application instantiates many balancers. + pub fn p2c_with_rng( + discover: D, + rng: &mut R, + ) -> Result { + let rng = SmallRng::from_rng(rng)?; + Ok(Self::new(discover, choose::PowerOfTwoChoices::new(rng))) + } +} + +impl Balance { + /// Attempts to choose services sequentially. + /// + /// This configuration is prefered when no load metric is known. + pub fn round_robin(discover: D) -> Self { + Self::new(discover, choose::RoundRobin::default()) + } +} + impl Balance where D: Discover,