feat(client): change GaiResolver to use a global blocking threadpool
BREAKING CHANGE: Calls to `GaiResolver::new` and `HttpConnector::new` no longer should pass an integer argument for the number of threads.
This commit is contained in:
@@ -38,7 +38,7 @@ pin-utils = "=0.1.0-alpha.4"
|
|||||||
time = "0.1"
|
time = "0.1"
|
||||||
tokio = { version = "=0.2.0-alpha.4", optional = true, default-features = false, features = ["rt-full"] }
|
tokio = { version = "=0.2.0-alpha.4", optional = true, default-features = false, features = ["rt-full"] }
|
||||||
tower-service = "=0.3.0-alpha.1"
|
tower-service = "=0.3.0-alpha.1"
|
||||||
tokio-executor = "=0.2.0-alpha.4"
|
tokio-executor = { version = "=0.2.0-alpha.4", features = ["blocking"] }
|
||||||
tokio-io = "=0.2.0-alpha.4"
|
tokio-io = "=0.2.0-alpha.4"
|
||||||
tokio-sync = "=0.2.0-alpha.4"
|
tokio-sync = "=0.2.0-alpha.4"
|
||||||
tokio-net = { version = "=0.2.0-alpha.4", optional = true, features = ["tcp"] }
|
tokio-net = { version = "=0.2.0-alpha.4", optional = true, features = ["tcp"] }
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ impl Opts {
|
|||||||
|
|
||||||
let addr = spawn_server(&mut rt, &self);
|
let addr = spawn_server(&mut rt, &self);
|
||||||
|
|
||||||
let connector = HttpConnector::new(1);
|
let connector = HttpConnector::new();
|
||||||
let client = hyper::Client::builder()
|
let client = hyper::Client::builder()
|
||||||
.http2_only(self.http2)
|
.http2_only(self.http2)
|
||||||
.http2_initial_stream_window_size(self.http2_stream_window)
|
.http2_initial_stream_window_size(self.http2_stream_window)
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ use std::net::{
|
|||||||
};
|
};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use futures_util::{FutureExt, StreamExt};
|
|
||||||
use tokio_sync::{mpsc, oneshot};
|
use tokio_sync::{mpsc, oneshot};
|
||||||
|
|
||||||
use crate::common::{Future, Never, Pin, Poll, Unpin, task};
|
use crate::common::{Future, Never, Pin, Poll, Unpin, task};
|
||||||
@@ -39,10 +38,7 @@ pub struct Name {
|
|||||||
/// A resolver using blocking `getaddrinfo` calls in a threadpool.
|
/// A resolver using blocking `getaddrinfo` calls in a threadpool.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct GaiResolver {
|
pub struct GaiResolver {
|
||||||
tx: tokio_executor::threadpool::Sender,
|
_priv: (),
|
||||||
/// A handle to keep the threadpool alive until all `GaiResolver` clones
|
|
||||||
/// have been dropped.
|
|
||||||
_threadpool_keep_alive: ThreadPoolKeepAlive,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -55,8 +51,7 @@ pub struct GaiAddrs {
|
|||||||
|
|
||||||
/// A future to resole a name returned by `GaiResolver`.
|
/// A future to resole a name returned by `GaiResolver`.
|
||||||
pub struct GaiFuture {
|
pub struct GaiFuture {
|
||||||
rx: oneshot::Receiver<Result<IpAddrs, io::Error>>,
|
inner: tokio_executor::blocking::Blocking<Result<IpAddrs, io::Error>>,
|
||||||
_threadpool_keep_alive: ThreadPoolKeepAlive,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Name {
|
impl Name {
|
||||||
@@ -108,40 +103,9 @@ impl Error for InvalidNameError {}
|
|||||||
|
|
||||||
impl GaiResolver {
|
impl GaiResolver {
|
||||||
/// Construct a new `GaiResolver`.
|
/// Construct a new `GaiResolver`.
|
||||||
///
|
pub fn new() -> Self {
|
||||||
/// Takes number of DNS worker threads.
|
|
||||||
pub fn new(threads: usize) -> Self {
|
|
||||||
let pool = tokio_executor::threadpool::Builder::new()
|
|
||||||
.name_prefix("hyper-dns-gai-resolver")
|
|
||||||
// not for CPU tasks, so only spawn workers
|
|
||||||
// in blocking mode
|
|
||||||
.pool_size(1)
|
|
||||||
.max_blocking(threads)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let tx = pool.sender().clone();
|
|
||||||
|
|
||||||
// The pool will start to shutdown once `pool` is dropped,
|
|
||||||
// so to keep it alive, we spawn a future onto the pool itself
|
|
||||||
// that will only resolve once all `GaiResolver` requests
|
|
||||||
// are finished.
|
|
||||||
let (shutdown_tx, shutdown_rx) = mpsc::channel(1);
|
|
||||||
|
|
||||||
let on_shutdown = shutdown_rx
|
|
||||||
.into_future()
|
|
||||||
.map(move |(next, _rx)| {
|
|
||||||
match next {
|
|
||||||
Some(never) => match never {},
|
|
||||||
None => (),
|
|
||||||
}
|
|
||||||
|
|
||||||
drop(pool)
|
|
||||||
});
|
|
||||||
tx.spawn(on_shutdown).expect("can spawn on self");
|
|
||||||
|
|
||||||
GaiResolver {
|
GaiResolver {
|
||||||
tx,
|
_priv: (),
|
||||||
_threadpool_keep_alive: ThreadPoolKeepAlive(shutdown_tx),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,14 +115,14 @@ impl Resolve for GaiResolver {
|
|||||||
type Future = GaiFuture;
|
type Future = GaiFuture;
|
||||||
|
|
||||||
fn resolve(&self, name: Name) -> Self::Future {
|
fn resolve(&self, name: Name) -> Self::Future {
|
||||||
let (tx, rx) = oneshot::channel();
|
let blocking = tokio_executor::blocking::run(move || {
|
||||||
self.tx.spawn(GaiBlocking {
|
debug!("resolving host={:?}", name.host);
|
||||||
host: name.host,
|
(&*name.host, 0).to_socket_addrs()
|
||||||
tx: Some(tx),
|
.map(|i| IpAddrs { iter: i })
|
||||||
}).expect("spawn GaiBlocking");
|
});
|
||||||
|
|
||||||
GaiFuture {
|
GaiFuture {
|
||||||
rx,
|
inner: blocking,
|
||||||
_threadpool_keep_alive: self._threadpool_keep_alive.clone(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,10 +137,9 @@ impl Future for GaiFuture {
|
|||||||
type Output = Result<GaiAddrs, io::Error>;
|
type Output = Result<GaiAddrs, io::Error>;
|
||||||
|
|
||||||
fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
|
fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
|
||||||
Pin::new(&mut self.rx).poll(cx).map(|res| match res {
|
Pin::new(&mut self.inner).poll(cx).map(|res| match res {
|
||||||
Ok(Ok(addrs)) => Ok(GaiAddrs { inner: addrs }),
|
Ok(addrs) => Ok(GaiAddrs { inner: addrs }),
|
||||||
Ok(Err(err)) => Err(err),
|
Err(err) => Err(err),
|
||||||
Err(_canceled) => unreachable!("GaiResolver threadpool shutdown"),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,9 +77,8 @@ impl HttpConnector {
|
|||||||
/// Construct a new HttpConnector.
|
/// Construct a new HttpConnector.
|
||||||
///
|
///
|
||||||
/// Takes number of DNS worker threads.
|
/// Takes number of DNS worker threads.
|
||||||
#[inline]
|
pub fn new() -> HttpConnector {
|
||||||
pub fn new(threads: usize) -> HttpConnector {
|
HttpConnector::new_with_resolver(GaiResolver::new())
|
||||||
HttpConnector::new_with_resolver(GaiResolver::new(threads))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1023,7 +1023,7 @@ impl Builder {
|
|||||||
B: Payload + Send,
|
B: Payload + Send,
|
||||||
B::Data: Send,
|
B::Data: Send,
|
||||||
{
|
{
|
||||||
let mut connector = HttpConnector::new(4);
|
let mut connector = HttpConnector::new();
|
||||||
if self.pool_config.enabled {
|
if self.pool_config.enabled {
|
||||||
connector.set_keepalive(self.pool_config.keep_alive_timeout);
|
connector.set_keepalive(self.pool_config.keep_alive_timeout);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ macro_rules! test {
|
|||||||
let addr = server.local_addr().expect("local_addr");
|
let addr = server.local_addr().expect("local_addr");
|
||||||
let rt = $runtime;
|
let rt = $runtime;
|
||||||
|
|
||||||
let connector = ::hyper::client::HttpConnector::new(1);
|
let connector = ::hyper::client::HttpConnector::new();
|
||||||
let client = Client::builder()
|
let client = Client::builder()
|
||||||
.set_host($set_host)
|
.set_host($set_host)
|
||||||
.http1_title_case_headers($title_case_headers)
|
.http1_title_case_headers($title_case_headers)
|
||||||
@@ -781,7 +781,7 @@ mod dispatch_impl {
|
|||||||
let mut rt = Runtime::new().unwrap();
|
let mut rt = Runtime::new().unwrap();
|
||||||
let (closes_tx, closes) = mpsc::channel(10);
|
let (closes_tx, closes) = mpsc::channel(10);
|
||||||
let client = Client::builder()
|
let client = Client::builder()
|
||||||
.build(DebugConnector::with_http_and_closes(HttpConnector::new(1), closes_tx));
|
.build(DebugConnector::with_http_and_closes(HttpConnector::new(), closes_tx));
|
||||||
|
|
||||||
let (tx1, rx1) = oneshot::channel();
|
let (tx1, rx1) = oneshot::channel();
|
||||||
|
|
||||||
@@ -837,7 +837,7 @@ mod dispatch_impl {
|
|||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
let client = Client::builder()
|
let client = Client::builder()
|
||||||
.build(DebugConnector::with_http_and_closes(HttpConnector::new(1), closes_tx));
|
.build(DebugConnector::with_http_and_closes(HttpConnector::new(), closes_tx));
|
||||||
|
|
||||||
let req = Request::builder()
|
let req = Request::builder()
|
||||||
.uri(&*format!("http://{}/a", addr))
|
.uri(&*format!("http://{}/a", addr))
|
||||||
@@ -889,7 +889,7 @@ mod dispatch_impl {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let client = Client::builder()
|
let client = Client::builder()
|
||||||
.build(DebugConnector::with_http_and_closes(HttpConnector::new(1), closes_tx));
|
.build(DebugConnector::with_http_and_closes(HttpConnector::new(), closes_tx));
|
||||||
|
|
||||||
let req = Request::builder()
|
let req = Request::builder()
|
||||||
.uri(&*format!("http://{}/a", addr))
|
.uri(&*format!("http://{}/a", addr))
|
||||||
@@ -948,7 +948,7 @@ mod dispatch_impl {
|
|||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
let client = Client::builder()
|
let client = Client::builder()
|
||||||
.build(DebugConnector::with_http_and_closes(HttpConnector::new(1), closes_tx));
|
.build(DebugConnector::with_http_and_closes(HttpConnector::new(), closes_tx));
|
||||||
|
|
||||||
let req = Request::builder()
|
let req = Request::builder()
|
||||||
.uri(&*format!("http://{}/a", addr))
|
.uri(&*format!("http://{}/a", addr))
|
||||||
@@ -996,7 +996,7 @@ mod dispatch_impl {
|
|||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
let client = Client::builder()
|
let client = Client::builder()
|
||||||
.build(DebugConnector::with_http_and_closes(HttpConnector::new(1), closes_tx));
|
.build(DebugConnector::with_http_and_closes(HttpConnector::new(), closes_tx));
|
||||||
|
|
||||||
let req = Request::builder()
|
let req = Request::builder()
|
||||||
.uri(&*format!("http://{}/a", addr))
|
.uri(&*format!("http://{}/a", addr))
|
||||||
@@ -1046,7 +1046,7 @@ mod dispatch_impl {
|
|||||||
|
|
||||||
let client = Client::builder()
|
let client = Client::builder()
|
||||||
.keep_alive(false)
|
.keep_alive(false)
|
||||||
.build(DebugConnector::with_http_and_closes(HttpConnector::new(1), closes_tx));
|
.build(DebugConnector::with_http_and_closes(HttpConnector::new(), closes_tx));
|
||||||
|
|
||||||
let req = Request::builder()
|
let req = Request::builder()
|
||||||
.uri(&*format!("http://{}/a", addr))
|
.uri(&*format!("http://{}/a", addr))
|
||||||
@@ -1090,7 +1090,7 @@ mod dispatch_impl {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let client = Client::builder()
|
let client = Client::builder()
|
||||||
.build(DebugConnector::with_http_and_closes(HttpConnector::new(1), closes_tx));
|
.build(DebugConnector::with_http_and_closes(HttpConnector::new(), closes_tx));
|
||||||
|
|
||||||
let req = Request::builder()
|
let req = Request::builder()
|
||||||
.uri(&*format!("http://{}/a", addr))
|
.uri(&*format!("http://{}/a", addr))
|
||||||
@@ -1527,7 +1527,7 @@ mod dispatch_impl {
|
|||||||
|
|
||||||
impl DebugConnector {
|
impl DebugConnector {
|
||||||
fn new() -> DebugConnector {
|
fn new() -> DebugConnector {
|
||||||
let http = HttpConnector::new(1);
|
let http = HttpConnector::new();
|
||||||
let (tx, _) = mpsc::channel(10);
|
let (tx, _) = mpsc::channel(10);
|
||||||
DebugConnector::with_http_and_closes(http, tx)
|
DebugConnector::with_http_and_closes(http, tx)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -313,7 +313,7 @@ pub fn __run_test(cfg: __TestConfig) {
|
|||||||
Version::HTTP_11
|
Version::HTTP_11
|
||||||
};
|
};
|
||||||
|
|
||||||
let connector = HttpConnector::new(1);
|
let connector = HttpConnector::new();
|
||||||
let client = Client::builder()
|
let client = Client::builder()
|
||||||
.keep_alive_timeout(Duration::from_secs(10))
|
.keep_alive_timeout(Duration::from_secs(10))
|
||||||
.http2_only(cfg.client_version == 2)
|
.http2_only(cfg.client_version == 2)
|
||||||
|
|||||||
Reference in New Issue
Block a user