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

Fix an issue where we are not injecting more HTTP2 connections when we should #56062

Merged
merged 2 commits into from
Jul 21, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -1822,6 +1822,9 @@ public void ReturnHttp2Connection(Http2Connection connection, bool isNewConnecti
if (NetEventSource.Log.IsEnabled()) connection.Trace("Dequeued waiting HTTP/2 request.");
}

// Since we only inject one connection at a time, we may want to inject another now.
CheckForHttp2ConnectionInjection();

if (_disposed)
{
// If the pool has been disposed of, we want to dispose the connection being returned, as the pool is being deactivated.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2118,6 +2118,63 @@ public async Task Http2_MultipleConnectionsEnabled_ConnectionLimitNotReached_Con
}
}

[ConditionalFact(nameof(SupportsAlpn))]
public async Task Http2_MultipleConnectionsEnabled_ManyRequestsEnqueuedSimultaneously_SufficientConnectionsCreated()
{
// This is equal to Http2Connection.InitialMaxConcurrentStreams, which is the limit we impose before we have received the peer's initial SETTINGS frame.
// Setting it to this value avoids any complexity that would occur from having to retry requests if the actual limit from the peer is lower.
const int MaxConcurrentStreams = 100;

const int ConnectionCount = 3;

// Just enough to force the third connection to be created.
const int RequestCount = (ConnectionCount - 1) * MaxConcurrentStreams + 1;

using Http2LoopbackServer server = Http2LoopbackServer.CreateServer();
server.AllowMultipleConnections = true;

using SocketsHttpHandler handler = CreateHandler();
using HttpClient client = CreateHttpClient(handler);

List<Task<HttpResponseMessage>> sendTasks = new List<Task<HttpResponseMessage>>();
for (int i = 0; i < RequestCount; i++)
{
var sendTask = client.GetAsync(server.Address);
sendTasks.Add(sendTask);
}

List<(Http2LoopbackConnection connection, int streamId)> acceptedRequests = new List<(Http2LoopbackConnection connection, int streamId)>();

using Http2LoopbackConnection c1 = await server.EstablishConnectionAsync(new SettingsEntry { SettingId = SettingId.MaxConcurrentStreams, Value = 100 });
for (int i = 0; i < MaxConcurrentStreams; i++)
{
(int streamId, _) = await c1.ReadAndParseRequestHeaderAsync();
acceptedRequests.Add((c1, streamId));
}

using Http2LoopbackConnection c2 = await server.EstablishConnectionAsync(new SettingsEntry { SettingId = SettingId.MaxConcurrentStreams, Value = 100 });
for (int i = 0; i < MaxConcurrentStreams; i++)
{
(int streamId, _) = await c2.ReadAndParseRequestHeaderAsync();
acceptedRequests.Add((c2, streamId));
}

using Http2LoopbackConnection c3 = await server.EstablishConnectionAsync(new SettingsEntry { SettingId = SettingId.MaxConcurrentStreams, Value = 100 });
(int finalStreamId, _) = await c3.ReadAndParseRequestHeaderAsync();
acceptedRequests.Add((c3, finalStreamId));

foreach ((Http2LoopbackConnection connection, int streamId) request in acceptedRequests)
{
await request.connection.SendDefaultResponseAsync(request.streamId);
}

foreach (Task<HttpResponseMessage> t in sendTasks)
{
HttpResponseMessage response = await t;
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}
}

[ConditionalFact(nameof(SupportsAlpn))]
[ActiveIssue("https://github.com/dotnet/runtime/issues/45204")]
public async Task Http2_MultipleConnectionsEnabled_InfiniteRequestsCompletelyBlockOneConnection_RemaningRequestsAreHandledByNewConnection()
Expand Down