-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Minimalistic HTTP2 flow control API #53372
Comments
Tagging subscribers to this area: @dotnet/ncl Issue DetailsThis is a replacement (next iteration) for #49897 Background and MotivationOur current HTTP/2 receive window size is 64 Kb, which is too small for many scenarios. It leads to poor throughput, see #43086 We are working on a dynamic window extension algorithm, which is expected to automatically grow the receive window, resulting in good throughput for the vast majority of the users. However, there could be cases when providing manual control over the window size might be a better option. My recommendation is to expose an API proactively for those corner cases. ExamplesThe algorithm needs RTT estimation which will be determined by sending PING frames periodically while reading the servers data. Although we are doing our best to make sure that we won't trigger today's server's PING flood detection with their default settings, theoretically it's possible that a strictly configured server may abort the connection. Facing such a case, a user could just disable the dynamic window algorithm (and therefore the PING frames), and set the window size manually. Another use case: since HTTP2 flow control is hop-by-hop, poorly configured intermediaries may alter the window sizes with H2C in a suboptimal way. I've experienced this by tunneling the connection through a VPN, where some intermediary (firewall?) was intercepting and replacing the WINDOW_UPDATE frames. With that connection, it wasn't possible to reach the desired throughput by extending the receive window with WINDOW_UPDATE's, however setting a large initial window worked. What about other knobs?I'm thinking of other parameters like the threshold divisor, or our arbitrarily high connection window increment as implementation details. Proposed APIpublic class SocketsHttpHandler
{
public bool EnableAutomaticHttp2StreamWindowExtension { get; set; } = true;
public int InitialHttp2StreamWindowSize { get; set; }
} Usage Examplesvar h = new SocketsHttpHandler {
// Disable the dynamic window algorithm and the periodic PING frames
EnableDynamicHttp2StreamWindowExtension = false,
// Set a 16MB receive window manually
InitialHttp2StreamWindowSize = 16*1024*1024
}; Alternative DesignsI'm not familiar with msquic flow control options, if there is an option to set the initial frame window size, we may consider to share the API between HTTP2 and HTTP3. @scalablecory thoughts? Is it worth an investigation? RisksNone.
|
@geoffkizer @scalablecory @CarnaViire let me know if you have any concerns or thoughts, we should catch the 6.0 train with this. |
Seems good to me. Maybe change Extension to Management or something in case we want to add window size reduction at some point. |
Yeah, and "Extension" is kind of a weird word, it makes me think you are extending the code somehow. I would suggest "EnableDynamicHttp2StreamWindowManagement" or "EnableDynamicHttp2StreamWindowSizing". |
@scalablecory Do you think these apply to HTTP3 as well? I can't recall how window management works with msquic. edit: msquic handles all of this for us, right? So we don't need a property here. |
|
Regarding QUIC & HTTP/3: I've been thinking about this, and now my opinion is that even if we decide to expose QUIC flow control options, it's better be done in separate properties in the future. I flipped this to be ready for review, @scalablecory @geoffkizer let me know if you disagree and we should discuss/change something before moving on. |
I think it's fine to make this HTTP/2 specific, because in HTTP/3's case the flow control is handled automatically by the transport (just like TCP). I could see us adding ways to tweak QUIC in the future, but we'd probably encourage setting those via a |
namespace System.Net.Http
{
public partial class SocketsHttpHandler
{
public int InitialHttp2StreamWindowSize { get; set; } // = 65535;
}
} |
This is a replacement (next iteration) of #49897
Background and Motivation
Our current HTTP/2 receive window size is 64 Kb, which is too small for many scenarios. It leads to poor throughput, see #43086
We are working on a dynamic window extension algorithm, which is expected to automatically grow the receive window, resulting in good throughput for the vast majority of the users. However, there could be cases when providing manual control over the window size might be a better option. My recommendation is to expose an API proactively for those corner cases.
Examples
The algorithm needs RTT estimation which will be determined by sending PING frames periodically while reading the servers data. Although we are doing our best to make sure that we won't trigger today's server's PING flood detection with their default settings, theoretically it's possible that a strictly configured server may abort the connection. Facing such a case, a user could just disable the dynamic window algorithm (and therefore the PING frames), and set the window size manually.
Another use case: since HTTP2 flow control is hop-by-hop, poorly configured intermediaries may alter the window sizes with H2C in a suboptimal way. I've experienced this by tunneling the connection through a VPN, where some intermediary (firewall?) was intercepting and replacing the WINDOW_UPDATE frames. With that connection, it wasn't possible to reach the desired throughput by extending the receive window with WINDOW_UPDATE's, however setting a large initial window worked.
What about other knobs?
I'm thinking of other parameters like the threshold divisor, or our arbitrarily high connection window increment as implementation details.
Proposed API
Usage Examples
Alternative Designs
[Edited]
EnableDynamicHttp2StreamWindowSizing
. The disadvantages are: (1) less visible docs (2) less accessible - which means that the user has to do much more facing an issue. Also: (3) can not be fine-tuned per-SocketsHttpHandler
. An explicit API feels better for this.Risks
None.
The text was updated successfully, but these errors were encountered: