feat(http2): add adaptive window size support using BDP (#2138)

This adds support for calculating the Bandwidth-delay product when using
HTTP2. When a DATA frame is received, a PING is sent to the remote.
While the PING acknoledgement is outstanding, the amount of bytes of all
received DATA frames is accumulated. Once we receive the PING
acknowledgement, we calculate the BDP based on the number of received
bytes and the round-trip-time of the PING. If we are near the current
maximum window size, the size is doubled.

It's disabled by default until tested more extensively.
This commit is contained in:
Sean McArthur
2020-02-25 16:00:50 -08:00
committed by GitHub
parent 22dc6fe4c6
commit 48102d6122
9 changed files with 451 additions and 71 deletions

View File

@@ -35,12 +35,6 @@ where
H2(#[pin] proto::h2::ClientTask<B>),
}
// Our defaults are chosen for the "majority" case, which usually are not
// resource constrained, and so the spec default of 64kb can be too limiting
// for performance.
const DEFAULT_HTTP2_CONN_WINDOW: u32 = 1024 * 1024 * 5; // 5mb
const DEFAULT_HTTP2_STREAM_WINDOW: u32 = 1024 * 1024 * 2; // 2mb
/// Returns a handshake future over some IO.
///
/// This is a shortcut for `Builder::new().handshake(io)`.
@@ -82,7 +76,7 @@ pub struct Builder {
h1_read_buf_exact_size: Option<usize>,
h1_max_buf_size: Option<usize>,
http2: bool,
h2_builder: h2::client::Builder,
h2_builder: proto::h2::client::Config,
}
/// A future returned by `SendRequest::send_request`.
@@ -420,12 +414,6 @@ impl Builder {
/// Creates a new connection builder.
#[inline]
pub fn new() -> Builder {
let mut h2_builder = h2::client::Builder::default();
h2_builder
.initial_window_size(DEFAULT_HTTP2_STREAM_WINDOW)
.initial_connection_window_size(DEFAULT_HTTP2_CONN_WINDOW)
.enable_push(false);
Builder {
exec: Exec::Default,
h1_writev: true,
@@ -433,7 +421,7 @@ impl Builder {
h1_title_case_headers: false,
h1_max_buf_size: None,
http2: false,
h2_builder,
h2_builder: Default::default(),
}
}
@@ -491,7 +479,8 @@ impl Builder {
/// [spec]: https://http2.github.io/http2-spec/#SETTINGS_INITIAL_WINDOW_SIZE
pub fn http2_initial_stream_window_size(&mut self, sz: impl Into<Option<u32>>) -> &mut Self {
if let Some(sz) = sz.into() {
self.h2_builder.initial_window_size(sz);
self.h2_builder.adaptive_window = false;
self.h2_builder.initial_stream_window_size = sz;
}
self
}
@@ -506,7 +495,24 @@ impl Builder {
sz: impl Into<Option<u32>>,
) -> &mut Self {
if let Some(sz) = sz.into() {
self.h2_builder.initial_connection_window_size(sz);
self.h2_builder.adaptive_window = false;
self.h2_builder.initial_conn_window_size = sz;
}
self
}
/// Sets whether to use an adaptive flow control.
///
/// Enabling this will override the limits set in
/// `http2_initial_stream_window_size` and
/// `http2_initial_connection_window_size`.
pub fn http2_adaptive_window(&mut self, enabled: bool) -> &mut Self {
use proto::h2::SPEC_WINDOW_SIZE;
self.h2_builder.adaptive_window = enabled;
if enabled {
self.h2_builder.initial_conn_window_size = SPEC_WINDOW_SIZE;
self.h2_builder.initial_stream_window_size = SPEC_WINDOW_SIZE;
}
self
}