Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

h2: enable HTTP/2 keepalive PING frames #737

Merged
merged 7 commits into from
Nov 12, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 24 additions & 8 deletions linkerd/app/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,28 +371,36 @@ pub fn parse_config<S: Strings>(strings: &S) -> Result<super::Config, EnvError>
let ingress_mode = parse(strings, ENV_INGRESS_MODE, parse_bool)?.unwrap_or(false);

let outbound = {
let keepalive = outbound_accept_keepalive?;
let bind = listen::Bind::new(
outbound_listener_addr?
.unwrap_or_else(|| parse_socket_addr(DEFAULT_OUTBOUND_LISTEN_ADDR).unwrap()),
outbound_accept_keepalive?,
keepalive,
);
let server = ServerConfig {
bind: bind.with_orig_dst_addr(outbound_orig_dst),
h2_settings,
h2_settings: h2::Settings {
keepalive_timeout: keepalive,
..h2_settings
},
};
let cache_max_idle_age =
outbound_cache_max_idle_age?.unwrap_or(DEFAULT_OUTBOUND_ROUTER_MAX_IDLE_AGE);
let max_idle =
outbound_max_idle_per_endoint?.unwrap_or(DEFAULT_OUTBOUND_MAX_IDLE_CONNS_PER_ENDPOINT);
let keepalive = outbound_connect_keepalive?;
let connect = ConnectConfig {
keepalive: outbound_connect_keepalive?,
keepalive,
timeout: outbound_connect_timeout?.unwrap_or(DEFAULT_OUTBOUND_CONNECT_TIMEOUT),
backoff: parse_backoff(
strings,
OUTBOUND_CONNECT_BASE,
DEFAULT_OUTBOUND_CONNECT_BACKOFF,
)?,
h2_settings,
h2_settings: h2::Settings {
keepalive_timeout: Keepalive,
..h2_settings,
},
h1_settings: h1::PoolSettings {
max_idle,
idle_timeout: cache_max_idle_age,
Expand Down Expand Up @@ -425,28 +433,36 @@ pub fn parse_config<S: Strings>(strings: &S) -> Result<super::Config, EnvError>
};

let inbound = {
let keepalive = inbound_accept_keepalive?;
let bind = listen::Bind::new(
inbound_listener_addr?
.unwrap_or_else(|| parse_socket_addr(DEFAULT_INBOUND_LISTEN_ADDR).unwrap()),
inbound_accept_keepalive?,
keepalive,
);
let server = ServerConfig {
bind: bind.with_orig_dst_addr(inbound_orig_dst),
h2_settings,
h2_settings: h2::Settings {
keepalive_timeout: keepalive,
..h2_settings
},
};
let cache_max_idle_age =
inbound_cache_max_idle_age?.unwrap_or(DEFAULT_INBOUND_ROUTER_MAX_IDLE_AGE);
let max_idle =
inbound_max_idle_per_endpoint?.unwrap_or(DEFAULT_INBOUND_MAX_IDLE_CONNS_PER_ENDPOINT);
let keepalive = inbound_connect_keepalive?;
let connect = ConnectConfig {
keepalive: inbound_connect_keepalive?,
keepalive,
timeout: inbound_connect_timeout?.unwrap_or(DEFAULT_INBOUND_CONNECT_TIMEOUT),
backoff: parse_backoff(
strings,
INBOUND_CONNECT_BASE,
DEFAULT_INBOUND_CONNECT_BACKOFF,
)?,
h2_settings,
h2_settings: h2::Settings {
keepalive_timeout: keepalive,
..h2_settings
},
h1_settings: h1::PoolSettings {
max_idle,
idle_timeout: cache_max_idle_age,
Expand Down
10 changes: 10 additions & 0 deletions linkerd/proxy/http/src/detect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@ impl<F, H> DetectHttp<F, H> {
.http2_initial_stream_window_size(h2.initial_stream_window_size)
.http2_initial_connection_window_size(h2.initial_connection_window_size);

// Configure HTTP/2 PING frames
if let Some(timeout) = h2.keepalive_timeout {
// XXX(eliza): is this a reasonable interval between
// PING frames?
let interval = timeout / 4;
server
.http2_keep_alive_timeout(timeout)
.http2_keep_alive_interval(interval);
}

Self {
server,
tcp,
Expand Down
22 changes: 19 additions & 3 deletions linkerd/proxy/http/src/h2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use hyper::{
client::conn::{self, SendRequest},
};
use linkerd2_error::Error;
use std::time::Duration;
use std::{
future::Future,
marker::PhantomData,
Expand All @@ -20,6 +21,7 @@ use tracing_futures::Instrument;
pub struct Settings {
pub initial_stream_window_size: Option<u32>,
pub initial_connection_window_size: Option<u32>,
pub keepalive_timeout: Option<Duration>,
}

#[derive(Debug)]
Expand Down Expand Up @@ -79,6 +81,7 @@ where
let Settings {
initial_connection_window_size,
initial_stream_window_size,
keepalive_timeout,
} = self.h2_settings;

let connect = self
Expand All @@ -89,12 +92,25 @@ where
Box::pin(
async move {
let io = connect.err_into::<Error>().await?;

let (tx, conn) = conn::Builder::new()
let mut builder = conn::Builder::new();
builder
.http2_only(true)
.http2_initial_stream_window_size(initial_stream_window_size)
.http2_initial_connection_window_size(initial_connection_window_size)
.executor(trace::Executor::new())
.executor(trace::Executor::new());

// Configure HTTP/2 PING frames
if let Some(timeout) = keepalive_timeout {
// XXX(eliza): is this a reasonable interval between
// PING frames?
let interval = timeout / 4;
builder
.http2_keep_alive_timeout(timeout)
.http2_keep_alive_interval(interval)
.http2_keep_alive_while_idle(true);
}

let (tx, conn) = conn::Builder::new()
.handshake(io)
.instrument(trace_span!("handshake"))
.await?;
Expand Down