Description
Feature Request
Crates
tonic
Motivation
From what I understood from #307, HTTP2 keep alive support was exposed only to the client (unless I missed some way of doing so for the server).
However hyper
also supports setting the keep alive interval and timeout for the server.
My motivation for this enhancement is well described here, which I quote:
KeepAlive provides a valuable benefit: periodically checking the health of the connection by sending an HTTP/2 PING to determine whether the connection is still alive. However it has another equally useful benefit: signaling liveness to proxies. Consider a client sending data to a server through a proxy. The client and server may be happy to keep a connection alive indefinitely, sending data as necessary. Proxies, on the other hand, are often quite resource constrained and may kill idle connections to save resources. Google Cloud Platform (GCP) load balancers disconnect apparently-idle connections after 10 minutes, and Amazon Web Services Elastic Load Balancers (AWS ELBs) disconnect them after 60 seconds
Proposal
I suggest that we only support setting http2_keep_alive_interval
, with something along the lines of:
--- a/tonic/Cargo.toml
+++ b/tonic/Cargo.toml
@@ -64,7 +64,7 @@ prost-derive = { version = "0.6", optional = true }
async-trait = { version = "0.1.13", optional = true }
# transport
-hyper = { version = "0.13.4", features = ["stream"], optional = true }
+hyper = { version = "0.13.4", features = ["stream", "runtime"], optional = true }
tokio = { version = "0.2.13", features = ["tcp"], optional = true }
tower = { version = "0.3", optional = true}
tower-make = { version = "0.3", features = ["connect"] }
--- a/tonic/src/transport/server/mod.rs
+++ b/tonic/src/transport/server/mod.rs
@@ -69,6 +69,7 @@ pub struct Server {
init_stream_window_size: Option<u32>,
init_connection_window_size: Option<u32>,
max_concurrent_streams: Option<u32>,
+ http2_keepalive_interval: Option<Duration>,
tcp_keepalive: Option<Duration>,
tcp_nodelay: bool,
}
@@ -221,6 +222,22 @@ impl Server {
}
}
+ /// Set whether HTTP2 Ping frames are enabled on accepted connections.
+ ///
+ /// If `None` is specified, HTTP2 keepalive is disabled, otherwise the duration
+ /// specified will be the time interval between HTTP2 Ping frames.
+ /// The timeout for receiving an acknowledgement of the keepalive ping is the default of
+ /// [hyper](https://docs.rs/hyper/0.13.4/hyper/server/struct.Builder.html#method.http2_keep_alive_timeout).
+ ///
+ /// Default is no HTTP2 keepalive (`None`)
+ ///
+ pub fn http2_keepalive_interval(self, http2_keepalive_interval: Option<Duration>) -> Self {
+ Server {
+ http2_keepalive_interval,
+ ..self
+ }
+ }
+
/// Set whether TCP keepalive messages are enabled on accepted connections.
///
/// If `None` is specified, keepalive is disabled, otherwise the duration
@@ -320,6 +337,7 @@ 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 http2_keepalive_interval = self.http2_keepalive_interval;
let timeout = self.timeout;
let tcp = incoming::tcp_incoming(incoming, self);
@@ -336,7 +354,8 @@ impl Server {
.http2_only(true)
.http2_initial_connection_window_size(init_connection_window_size)
.http2_initial_stream_window_size(init_stream_window_size)
- .http2_max_concurrent_streams(max_concurrent_streams);
+ .http2_max_concurrent_streams(max_concurrent_streams)
+ .http2_keep_alive_interval(http2_keepalive_interval);
if let Some(signal) = signal {
server
This proposal leaves http2_keep_alive_timeout
to be whichever hyper
defaults to (currently 20 seconds).
Note that the code above has not been compiled or tested, I'm happy to submit a PR if you guys think this change is worth it.
The main drawback I see is that the runtime
feature of hyper
must be enabled for hyper::server::Builder::http2_keep_alive_interval
to be used (link).
Alternatives
None that I can think of, but I welcome any suggestions :D
Note
Thanks in advance for your help and thank you for the great work on tonic, hats off!