From 39e03a91e28ef3d42b8a4d1a70fbca3367779155 Mon Sep 17 00:00:00 2001 From: Sean McArthur Date: Thu, 15 Feb 2018 12:49:52 -0800 Subject: [PATCH] perf(server): set TCP keepalive when default listener is used --- src/server/mod.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/server/mod.rs b/src/server/mod.rs index 80343c2a..258c059b 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -100,6 +100,7 @@ pub struct SpawnAll { #[derive(Debug)] pub struct AddrIncoming { addr: SocketAddr, + keep_alive_timeout: Option, listener: TcpListener, } @@ -224,7 +225,10 @@ impl + 'static> Http { Bd: Stream, { let listener = TcpListener::bind(addr, &handle)?; - let incoming = AddrIncoming::new(listener)?; + let mut incoming = AddrIncoming::new(listener)?; + if self.keep_alive { + incoming.set_keepalive(Some(Duration::from_secs(90))); + } Ok(self.serve_incoming(incoming, new_service)) } @@ -362,7 +366,11 @@ impl Server let handle = reactor.handle(); - let incoming = AddrIncoming::new(listener)?; + let mut incoming = AddrIncoming::new(listener)?; + + if protocol.keep_alive { + incoming.set_keepalive(Some(Duration::from_secs(90))); + } // Mini future to track the number of active services let info = Rc::new(RefCell::new(Info { @@ -586,6 +594,7 @@ impl AddrIncoming { fn new(listener: TcpListener) -> io::Result { Ok(AddrIncoming { addr: listener.local_addr()?, + keep_alive_timeout: None, listener: listener, }) } @@ -594,6 +603,10 @@ impl AddrIncoming { pub fn local_addr(&self) -> SocketAddr { self.addr } + + fn set_keepalive(&mut self, dur: Option) { + self.keep_alive_timeout = dur; + } } impl Stream for AddrIncoming { @@ -605,6 +618,11 @@ impl Stream for AddrIncoming { loop { match self.listener.accept() { Ok((socket, addr)) => { + if let Some(dur) = self.keep_alive_timeout { + if let Err(e) = socket.set_keepalive(Some(dur)) { + trace!("error trying to set TCP keepalive: {}", e); + } + } return Ok(Async::Ready(Some(AddrStream::new(socket, addr)))); }, Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => return Ok(Async::NotReady),