perf(client): set TCP keepalive when default connector is used
This commit is contained in:
@@ -3,7 +3,7 @@ use std::fmt;
|
|||||||
use std::io;
|
use std::io;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
//use std::net::SocketAddr;
|
use std::time::Duration;
|
||||||
|
|
||||||
use futures::{Future, Poll, Async};
|
use futures::{Future, Poll, Async};
|
||||||
use futures::future::{Executor, ExecuteError};
|
use futures::future::{Executor, ExecuteError};
|
||||||
@@ -50,6 +50,7 @@ pub struct HttpConnector {
|
|||||||
executor: HttpConnectExecutor,
|
executor: HttpConnectExecutor,
|
||||||
enforce_http: bool,
|
enforce_http: bool,
|
||||||
handle: Handle,
|
handle: Handle,
|
||||||
|
keep_alive_timeout: Option<Duration>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HttpConnector {
|
impl HttpConnector {
|
||||||
@@ -75,7 +76,8 @@ impl HttpConnector {
|
|||||||
HttpConnector {
|
HttpConnector {
|
||||||
executor: HttpConnectExecutor(Arc::new(executor)),
|
executor: HttpConnectExecutor(Arc::new(executor)),
|
||||||
enforce_http: true,
|
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) {
|
pub fn enforce_http(&mut self, is_enforced: bool) {
|
||||||
self.enforce_http = is_enforced;
|
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 {
|
impl fmt::Debug for HttpConnector {
|
||||||
@@ -128,6 +140,7 @@ impl Service for HttpConnector {
|
|||||||
HttpConnecting {
|
HttpConnecting {
|
||||||
state: State::Lazy(self.executor.clone(), host.into(), port),
|
state: State::Lazy(self.executor.clone(), host.into(), port),
|
||||||
handle: self.handle.clone(),
|
handle: self.handle.clone(),
|
||||||
|
keep_alive_timeout: self.keep_alive_timeout,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,6 +150,7 @@ fn invalid_url(err: InvalidUrl, handle: &Handle) -> HttpConnecting {
|
|||||||
HttpConnecting {
|
HttpConnecting {
|
||||||
state: State::Error(Some(io::Error::new(io::ErrorKind::InvalidInput, err))),
|
state: State::Error(Some(io::Error::new(io::ErrorKind::InvalidInput, err))),
|
||||||
handle: handle.clone(),
|
handle: handle.clone(),
|
||||||
|
keep_alive_timeout: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,6 +182,7 @@ impl StdError for InvalidUrl {
|
|||||||
pub struct HttpConnecting {
|
pub struct HttpConnecting {
|
||||||
state: State,
|
state: State,
|
||||||
handle: Handle,
|
handle: Handle,
|
||||||
|
keep_alive_timeout: Option<Duration>,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum State {
|
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")),
|
State::Error(ref mut e) => return Err(e.take().expect("polled more than once")),
|
||||||
}
|
}
|
||||||
self.state = state;
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|||||||
@@ -544,7 +544,11 @@ where B: Stream<Error=::Error>,
|
|||||||
/// Construct the Client with this configuration.
|
/// Construct the Client with this configuration.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn build(self, handle: &Handle) -> Client<HttpConnector, B> {
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user