balance: Move constructors under `Balance` (#82)

Previously, `power_of_two_choices` and `round_robin` constructors were
exposed from the crate scope.

These have been replaced by `Balance::p2c`, `Balance::p2c_from_rng`, and
`Balance::round_robin`.
This commit is contained in:
Oliver Gould 2018-06-05 13:10:00 -07:00 committed by GitHub
parent 5030a4f852
commit c0f52bb259
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 49 additions and 32 deletions

View File

@ -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)
});

View File

@ -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<D>(loaded: D) -> Balance<D, choose::PowerOfTwoChoices>
where
D: Discover,
D::Service: Load,
<D::Service as 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<D: Discover>(discover: D) -> Balance<D, choose::RoundRobin> {
Balance::new(discover, choose::RoundRobin::default())
}
/// Balances requests across a set of inner services.
#[derive(Debug)]
pub struct Balance<D: Discover, C> {
@ -90,6 +61,52 @@ pub struct ResponseFuture<F: Future, E>(F, PhantomData<E>);
// ===== impl Balance =====
impl<D> Balance<D, choose::PowerOfTwoChoices>
where
D: Discover,
D::Service: Load,
<D::Service as 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<R: rand::Rng>(
discover: D,
rng: &mut R,
) -> Result<Self, rand::Error> {
let rng = SmallRng::from_rng(rng)?;
Ok(Self::new(discover, choose::PowerOfTwoChoices::new(rng)))
}
}
impl<D: Discover> Balance<D, choose::RoundRobin> {
/// 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<D, C> Balance<D, C>
where
D: Discover,