From ac8934a58155bb0053dc1b09f93c3ea8503195ec Mon Sep 17 00:00:00 2001 From: Philippe GASSMANN Date: Fri, 22 Nov 2019 16:13:42 +0100 Subject: [PATCH 1/3] Allow to set tcp keepalive on bind --- tonic/src/transport/server.rs | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/tonic/src/transport/server.rs b/tonic/src/transport/server.rs index 9c87c14bf..dc7eba696 100644 --- a/tonic/src/transport/server.rs +++ b/tonic/src/transport/server.rs @@ -11,6 +11,7 @@ use hyper::{ server::{accept::Accept, conn}, Body, }; +use std::time::Duration; use std::{ fmt, future::Future, @@ -51,6 +52,7 @@ pub struct Server { init_stream_window_size: Option, init_connection_window_size: Option, max_concurrent_streams: Option, + tcp_keepalive: Option, } /// A stack based `Service` router. @@ -144,6 +146,21 @@ impl Server { } } + /// Set whether TCP keepalive messages are enabled on accepted connections. + /// + /// If `None` is specified, keepalive is disabled, otherwise the duration + /// specified will be the time to remain idle before sending TCP keepalive + /// probes. + /// + /// Default is no keepalive (`None`) + /// + pub fn tcp_keepalive(self, tcp_keepalive: Option) -> Self { + Server { + tcp_keepalive, + ..self + } + } + /// Intercept the execution of gRPC methods. /// /// ``` @@ -201,12 +218,14 @@ impl Server { let init_connection_window_size = self.init_connection_window_size; let init_stream_window_size = self.init_stream_window_size; let max_concurrent_streams = self.max_concurrent_streams; + let tcp_keepalive = self.tcp_keepalive; // let timeout = self.timeout.clone(); let incoming = hyper::server::accept::from_stream(async_stream::try_stream! { - let mut tcp = TcpIncoming::bind(addr)?; + let mut tcp = TcpIncoming::bind(addr, tcp_keepalive)?; while let Some(stream) = tcp.try_next().await? { + #[cfg(feature = "tls")] { if let Some(tls) = &self.tls { @@ -395,9 +414,10 @@ struct TcpIncoming { } impl TcpIncoming { - fn bind(addr: SocketAddr) -> Result { + fn bind(addr: SocketAddr, tcp_keepalive: Option) -> Result { let mut inner = conn::AddrIncoming::bind(&addr).map_err(Box::new)?; inner.set_nodelay(true); + inner.set_keepalive(tcp_keepalive); Ok(Self { inner }) } From 3f91c7500ca3168eb566e1c323dc78ad09eb7d2a Mon Sep 17 00:00:00 2001 From: Philippe GASSMANN Date: Fri, 22 Nov 2019 16:36:17 +0100 Subject: [PATCH 2/3] Allow to set tcp keepalive on client Endpoint --- tonic/src/transport/endpoint.rs | 17 +++++++++++++++++ tonic/src/transport/service/connection.rs | 4 ++-- tonic/src/transport/service/connector.rs | 12 +++++++----- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/tonic/src/transport/endpoint.rs b/tonic/src/transport/endpoint.rs index 0a4f32dcc..09aea0ef6 100644 --- a/tonic/src/transport/endpoint.rs +++ b/tonic/src/transport/endpoint.rs @@ -29,6 +29,7 @@ pub struct Endpoint { Option>, pub(super) init_stream_window_size: Option, pub(super) init_connection_window_size: Option, + pub(super) tcp_keepalive: Option, } impl Endpoint { @@ -83,6 +84,21 @@ impl Endpoint { } } + /// Set whether TCP keepalive messages are enabled on accepted connections. + /// + /// If `None` is specified, keepalive is disabled, otherwise the duration + /// specified will be the time to remain idle before sending TCP keepalive + /// probes. + /// + /// Default is no keepalive (`None`) + /// + pub fn tcp_keepalive(self, tcp_keepalive: Option) -> Self { + Endpoint { + tcp_keepalive, + ..self + } + } + /// Apply a concurrency limit to each request. /// /// ``` @@ -174,6 +190,7 @@ impl From for Endpoint { interceptor_headers: None, init_stream_window_size: None, init_connection_window_size: None, + tcp_keepalive: None, } } } diff --git a/tonic/src/transport/service/connection.rs b/tonic/src/transport/service/connection.rs index 47693b35e..32daf8b0e 100644 --- a/tonic/src/transport/service/connection.rs +++ b/tonic/src/transport/service/connection.rs @@ -28,10 +28,10 @@ pub(crate) struct Connection { impl Connection { pub(crate) async fn new(endpoint: Endpoint) -> Result { #[cfg(feature = "tls")] - let connector = connector(endpoint.tls.clone()); + let connector = connector(endpoint.tls.clone(), endpoint.tcp_keepalive.clone()); #[cfg(not(feature = "tls"))] - let connector = connector(); + let connector = connector(endpoint.tcp_keepalive.clone()); let settings = Builder::new() .http2_initial_stream_window_size(endpoint.init_stream_window_size) diff --git a/tonic/src/transport/service/connector.rs b/tonic/src/transport/service/connector.rs index c02d17367..17e2d8d41 100644 --- a/tonic/src/transport/service/connector.rs +++ b/tonic/src/transport/service/connector.rs @@ -6,20 +6,22 @@ use hyper::client::connect::HttpConnector; use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll}; +use std::time::Duration; use tower_make::MakeConnection; use tower_service::Service; #[cfg(not(feature = "tls"))] -pub(crate) fn connector() -> HttpConnector { +pub(crate) fn connector(tcp_keepalive: Option) -> HttpConnector { let mut http = HttpConnector::new(); http.enforce_http(false); http.set_nodelay(true); + http.set_keepalive(tcp_keepalive); http } #[cfg(feature = "tls")] -pub(crate) fn connector(tls: Option) -> Connector { - Connector::new(tls) +pub(crate) fn connector(tls: Option, tcp_keepalive: Option) -> Connector { + Connector::new(tls, tcp_keepalive) } pub(crate) struct Connector { @@ -30,11 +32,11 @@ pub(crate) struct Connector { impl Connector { #[cfg(feature = "tls")] - pub(crate) fn new(tls: Option) -> Self { + pub(crate) fn new(tls: Option, tcp_keepalive: Option) -> Self { let mut http = HttpConnector::new(); http.enforce_http(false); http.set_nodelay(true); - + http.set_keepalive(tcp_keepalive); Self { http, tls } } } From 0aead9546fa1f75bb02aebbc11b2d8100f217e8d Mon Sep 17 00:00:00 2001 From: Philippe GASSMANN Date: Fri, 22 Nov 2019 20:16:49 +0100 Subject: [PATCH 3/3] remove useless clone --- tonic/src/transport/service/connection.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tonic/src/transport/service/connection.rs b/tonic/src/transport/service/connection.rs index 32daf8b0e..10fcf3545 100644 --- a/tonic/src/transport/service/connection.rs +++ b/tonic/src/transport/service/connection.rs @@ -28,10 +28,10 @@ pub(crate) struct Connection { impl Connection { pub(crate) async fn new(endpoint: Endpoint) -> Result { #[cfg(feature = "tls")] - let connector = connector(endpoint.tls.clone(), endpoint.tcp_keepalive.clone()); + let connector = connector(endpoint.tls.clone(), endpoint.tcp_keepalive); #[cfg(not(feature = "tls"))] - let connector = connector(endpoint.tcp_keepalive.clone()); + let connector = connector(endpoint.tcp_keepalive); let settings = Builder::new() .http2_initial_stream_window_size(endpoint.init_stream_window_size)