perf(client): set TCP keepalive when default connector is used

This commit is contained in:
Sean McArthur
2018-02-15 12:40:38 -08:00
parent ee61ea9adf
commit 6ef22da8ea
2 changed files with 31 additions and 16 deletions

View File

@@ -3,7 +3,7 @@ use std::fmt;
use std::io;
use std::mem;
use std::sync::Arc;
//use std::net::SocketAddr;
use std::time::Duration;
use futures::{Future, Poll, Async};
use futures::future::{Executor, ExecuteError};
@@ -50,6 +50,7 @@ pub struct HttpConnector {
executor: HttpConnectExecutor,
enforce_http: bool,
handle: Handle,
keep_alive_timeout: Option<Duration>,
}
impl HttpConnector {
@@ -75,7 +76,8 @@ impl HttpConnector {
HttpConnector {
executor: HttpConnectExecutor(Arc::new(executor)),
enforce_http: true,
handle: handle.clone()
handle: handle.clone(),
keep_alive_timeout: None,
}
}
@@ -86,6 +88,16 @@ impl HttpConnector {
pub fn enforce_http(&mut self, is_enforced: bool) {
self.enforce_http = is_enforced;
}
/// Set that all sockets have `SO_KEEPALIVE` set with the supplied duration.
///
/// If `None`, the option will not be set.
///
/// Default is `None`.
#[inline]
pub fn set_keepalive(&mut self, dur: Option<Duration>) {
self.keep_alive_timeout = dur;
}
}
impl fmt::Debug for HttpConnector {
@@ -128,6 +140,7 @@ impl Service for HttpConnector {
HttpConnecting {
state: State::Lazy(self.executor.clone(), host.into(), port),
handle: self.handle.clone(),
keep_alive_timeout: self.keep_alive_timeout,
}
}
}
@@ -137,6 +150,7 @@ fn invalid_url(err: InvalidUrl, handle: &Handle) -> HttpConnecting {
HttpConnecting {
state: State::Error(Some(io::Error::new(io::ErrorKind::InvalidInput, err))),
handle: handle.clone(),
keep_alive_timeout: None,
}
}
@@ -168,6 +182,7 @@ impl StdError for InvalidUrl {
pub struct HttpConnecting {
state: State,
handle: Handle,
keep_alive_timeout: Option<Duration>,
}
enum State {
@@ -210,7 +225,15 @@ impl Future for HttpConnecting {
}
};
},
State::Connecting(ref mut c) => return c.poll(&self.handle).map_err(From::from),
State::Connecting(ref mut c) => {
let mut sock = try_ready!(c.poll(&self.handle));
if let Some(dur) = self.keep_alive_timeout {
sock.set_keepalive(Some(dur))?;
}
return Ok(Async::Ready(sock));
},
State::Error(ref mut e) => return Err(e.take().expect("polled more than once")),
}
self.state = state;
@@ -288,18 +311,6 @@ impl Executor<oneshot::Execute<dns::Work>> for HttpConnectExecutor {
}
}
/*
impl<S: SslClient> HttpsConnector<S> {
/// Create a new connector using the provided SSL implementation.
pub fn new(s: S) -> HttpsConnector<S> {
HttpsConnector {
http: HttpConnector::default(),
ssl: s,
}
}
}
*/
#[cfg(test)]
mod tests {
use std::io;

View File

@@ -544,7 +544,11 @@ where B: Stream<Error=::Error>,
/// Construct the Client with this configuration.
#[inline]
pub fn build(self, handle: &Handle) -> Client<HttpConnector, B> {
self.connector(HttpConnector::new(4, handle)).build(handle)
let mut connector = HttpConnector::new(4, handle);
if self.keep_alive {
connector.set_keepalive(self.keep_alive_timeout);
}
self.connector(connector).build(handle)
}
}