Skip to content

Commit caccfad

Browse files
zenriaLucioFranco
authored andcommitted
feat(transport): Expose tcp keepalive to clients & servers (#151)
1 parent 3387ef9 commit caccfad

File tree

4 files changed

+47
-9
lines changed

4 files changed

+47
-9
lines changed

tonic/src/transport/endpoint.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ pub struct Endpoint {
2929
Option<Arc<dyn Fn(&mut http::HeaderMap) + Send + Sync + 'static>>,
3030
pub(super) init_stream_window_size: Option<u32>,
3131
pub(super) init_connection_window_size: Option<u32>,
32+
pub(super) tcp_keepalive: Option<Duration>,
3233
}
3334

3435
impl Endpoint {
@@ -83,6 +84,21 @@ impl Endpoint {
8384
}
8485
}
8586

87+
/// Set whether TCP keepalive messages are enabled on accepted connections.
88+
///
89+
/// If `None` is specified, keepalive is disabled, otherwise the duration
90+
/// specified will be the time to remain idle before sending TCP keepalive
91+
/// probes.
92+
///
93+
/// Default is no keepalive (`None`)
94+
///
95+
pub fn tcp_keepalive(self, tcp_keepalive: Option<Duration>) -> Self {
96+
Endpoint {
97+
tcp_keepalive,
98+
..self
99+
}
100+
}
101+
86102
/// Apply a concurrency limit to each request.
87103
///
88104
/// ```
@@ -174,6 +190,7 @@ impl From<Uri> for Endpoint {
174190
interceptor_headers: None,
175191
init_stream_window_size: None,
176192
init_connection_window_size: None,
193+
tcp_keepalive: None,
177194
}
178195
}
179196
}

tonic/src/transport/server.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use hyper::{
1414
server::{accept::Accept, conn},
1515
Body,
1616
};
17+
use std::time::Duration;
1718
use std::{
1819
fmt,
1920
future::Future,
@@ -54,6 +55,7 @@ pub struct Server {
5455
init_stream_window_size: Option<u32>,
5556
init_connection_window_size: Option<u32>,
5657
max_concurrent_streams: Option<u32>,
58+
tcp_keepalive: Option<Duration>,
5759
}
5860

5961
/// A stack based `Service` router.
@@ -147,6 +149,21 @@ impl Server {
147149
}
148150
}
149151

152+
/// Set whether TCP keepalive messages are enabled on accepted connections.
153+
///
154+
/// If `None` is specified, keepalive is disabled, otherwise the duration
155+
/// specified will be the time to remain idle before sending TCP keepalive
156+
/// probes.
157+
///
158+
/// Default is no keepalive (`None`)
159+
///
160+
pub fn tcp_keepalive(self, tcp_keepalive: Option<Duration>) -> Self {
161+
Server {
162+
tcp_keepalive,
163+
..self
164+
}
165+
}
166+
150167
/// Intercept the execution of gRPC methods.
151168
///
152169
/// ```
@@ -204,11 +221,12 @@ impl Server {
204221
let init_connection_window_size = self.init_connection_window_size;
205222
let init_stream_window_size = self.init_stream_window_size;
206223
let max_concurrent_streams = self.max_concurrent_streams;
224+
let tcp_keepalive = self.tcp_keepalive;
207225
// let timeout = self.timeout.clone();
208226

209227
let incoming = hyper::server::accept::from_stream::<_, _, crate::Error>(
210228
async_stream::try_stream! {
211-
let mut tcp = TcpIncoming::bind(addr)?;
229+
let mut tcp = TcpIncoming::bind(addr, tcp_keepalive)?;
212230

213231
while let Some(stream) = tcp.try_next().await? {
214232
#[cfg(feature = "tls")]
@@ -400,9 +418,10 @@ struct TcpIncoming {
400418
}
401419

402420
impl TcpIncoming {
403-
fn bind(addr: SocketAddr) -> Result<Self, crate::Error> {
421+
fn bind(addr: SocketAddr, tcp_keepalive: Option<Duration>) -> Result<Self, crate::Error> {
404422
let mut inner = conn::AddrIncoming::bind(&addr).map_err(Box::new)?;
405423
inner.set_nodelay(true);
424+
inner.set_keepalive(tcp_keepalive);
406425

407426
Ok(Self { inner })
408427
}

tonic/src/transport/service/connection.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ pub(crate) struct Connection {
2828
impl Connection {
2929
pub(crate) async fn new(endpoint: Endpoint) -> Result<Self, crate::Error> {
3030
#[cfg(feature = "tls")]
31-
let connector = connector(endpoint.tls.clone());
31+
let connector = connector(endpoint.tls.clone(), endpoint.tcp_keepalive);
3232

3333
#[cfg(not(feature = "tls"))]
34-
let connector = connector();
34+
let connector = connector(endpoint.tcp_keepalive);
3535

3636
let settings = Builder::new()
3737
.http2_initial_stream_window_size(endpoint.init_stream_window_size)

tonic/src/transport/service/connector.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,22 @@ use hyper::client::connect::HttpConnector;
66
use std::future::Future;
77
use std::pin::Pin;
88
use std::task::{Context, Poll};
9+
use std::time::Duration;
910
use tower_make::MakeConnection;
1011
use tower_service::Service;
1112

1213
#[cfg(not(feature = "tls"))]
13-
pub(crate) fn connector() -> HttpConnector {
14+
pub(crate) fn connector(tcp_keepalive: Option<Duration>) -> HttpConnector {
1415
let mut http = HttpConnector::new();
1516
http.enforce_http(false);
1617
http.set_nodelay(true);
18+
http.set_keepalive(tcp_keepalive);
1719
http
1820
}
1921

2022
#[cfg(feature = "tls")]
21-
pub(crate) fn connector(tls: Option<TlsConnector>) -> Connector {
22-
Connector::new(tls)
23+
pub(crate) fn connector(tls: Option<TlsConnector>, tcp_keepalive: Option<Duration>) -> Connector {
24+
Connector::new(tls, tcp_keepalive)
2325
}
2426

2527
pub(crate) struct Connector {
@@ -30,11 +32,11 @@ pub(crate) struct Connector {
3032

3133
impl Connector {
3234
#[cfg(feature = "tls")]
33-
pub(crate) fn new(tls: Option<TlsConnector>) -> Self {
35+
pub(crate) fn new(tls: Option<TlsConnector>, tcp_keepalive: Option<Duration>) -> Self {
3436
let mut http = HttpConnector::new();
3537
http.enforce_http(false);
3638
http.set_nodelay(true);
37-
39+
http.set_keepalive(tcp_keepalive);
3840
Self { http, tls }
3941
}
4042
}

0 commit comments

Comments
 (0)