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

SocketsHttpHandler should use first available connection (don't wait on new connection creation) #44818

Closed
geoffkizer opened this issue Nov 17, 2020 · 9 comments · Fixed by #53851
Assignees
Labels
area-System.Net.Http Cost:M Work that requires one engineer up to 2 weeks enhancement Product code improvement that does NOT require public API changes/additions Priority:2 Work that is important, but not critical for the release tenet-performance Performance related issue
Milestone

Comments

@geoffkizer
Copy link
Contributor

geoffkizer commented Nov 17, 2020

AB#1254012
Currently, when we have no idle HTTP/1.1 connections (and are not at the connection limit) and a new request comes in, we will create a new connection and then use it for the new request.

The connect itself may take a while, especially for HTTPS connections. During this time, an existing connection may complete its current request and become available. If so, we should just use this idle connection instead of waiting for the new connection to finish its connect.

This should help request latency, and probably reduce the number of connections created during burst usage as well (see #43764).

More details:

When this happens, the new connection can still be put in the pool as idle, even if we don't have a request for it at the moment. If another new request comes in, we will use it like any other idle connection.

Note also that we should avoid creating new connections when we already have enough pending connections to (eventually) handle all the pending requests. Consider this scenario, starting with no connections:

  • Request A arrives, we initiate a connect for Connection 1, wait for it, and start processing A on it
  • Request B arrives, we initiate a connect for Connection 2. Before the connect completes, A finishes and Connection 1 becomes available. We start processing B on Connection 1.
  • Request C arrives. There's no established connection for it to use, but there is a pending connection (Connection 2). So there's no need for us to initiate another connection right now.
  • Request D arrives. Now, we have 0 available connections, 1 pending connection (Connection 2), and 2 pending requests (C and D). So we should go ahead and initiate a new connect for Connection 3.
@geoffkizer geoffkizer added this to the 6.0.0 milestone Nov 17, 2020
@ghost
Copy link

ghost commented Nov 17, 2020

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details
Description:

Currently, when we have no idle HTTP/1.1 connections (and are not at the connection limit) and a new request comes in, we will create a new connection and then use it for the new request.

The connect itself may take a while, especially for HTTPS connections. During this time, an existing connection may complete its current request and become available. If so, we should just use this idle connection instead of waiting for the new connection to finish its connect.

This should help request latency, and probably reduce the number of connections created during burst usage as well (see #43764).

More details:

When this happens, the new connection can still be put in the pool as idle, even if we don't have a request for it at the moment. If another new request comes in, we will use it like any other idle connection.

Note also that we should avoid creating new connections when we already have enough pending connections to (eventually) handle all the pending requests. Consider this scenario, starting with no connections:

  • Request A arrives, we initiate a connect for Connection 1, wait for it, and start processing A on it
  • Request B arrives, we initiate a connect for Connection 2. Before the connect completes, A finishes and Connection 1 becomes available. We start processing B on Connection 1.
  • Request C arrives. There's no established connection for it to use, but there is a pending connection (Connection 2). So there's no need for us to initiate another connection right now.
  • Request D arrives. Now, we have 0 available connections, 1 pending connection (Connection 2), and 2 pending requests (C and D). So we should go ahead and initiate a new connect for Connection 3.
Author: geoffkizer
Assignees: -
Labels:

area-System.Net.Http, tenet-performance

Milestone: [object Object]

@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added the untriaged New issue has not been triaged by the area owner label Nov 17, 2020
@Tratcher
Copy link
Member

Could the same approach be used for HTTP/2 when EnableMultipleHttp2Connections is enabled?

@geoffkizer
Copy link
Contributor Author

Could the same approach be used for HTTP/2 when EnableMultipleHttp2Connections is enabled?

Potentially, yeah. It's a different set of logic though. The way EnableMultipleHttp2Connections works is a bit wonky today, so we should probably consider this as part of a general cleanup here.

@stephentoub
Copy link
Member

Seems like a reasonable thing to do, albeit likely adding some implementation trickiness (in particular when it intersects with a set MaxConnectionsPerServer) to what is largely a straightforward process today.

@karelz karelz added enhancement Product code improvement that does NOT require public API changes/additions untriaged New issue has not been triaged by the area owner and removed untriaged New issue has not been triaged by the area owner labels Dec 2, 2020
@gmorris007

This comment has been minimized.

@wfurt

This comment has been minimized.

@gmorris007

This comment has been minimized.

@wfurt

This comment has been minimized.

@karelz

This comment has been minimized.

@karelz karelz removed the untriaged New issue has not been triaged by the area owner label Dec 3, 2020
@karelz karelz added the Bottom Up Work Not part of a theme, epic, or user story label Dec 7, 2020
@karelz karelz added the User Story A single user-facing feature. Can be grouped under an epic. label Dec 10, 2020
@karelz karelz added Priority:2 Work that is important, but not critical for the release Team:Libraries Cost:M Work that requires one engineer up to 2 weeks labels Jan 4, 2021
@karelz karelz changed the title SocketsHttpHandler should use an existing connection if it becomes available, instead of waiting for a new connect attempt to complete SocketsHttpHandler should use first available connection (don't wait on new connection creation) Jan 12, 2021
@karelz karelz removed the Bottom Up Work Not part of a theme, epic, or user story label Jan 12, 2021
@karelz karelz removed Team:Libraries User Story A single user-facing feature. Can be grouped under an epic. labels Jan 12, 2021
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Jun 8, 2021
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Jul 15, 2021
@ghost ghost locked as resolved and limited conversation to collaborators Aug 14, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Net.Http Cost:M Work that requires one engineer up to 2 weeks enhancement Product code improvement that does NOT require public API changes/additions Priority:2 Work that is important, but not critical for the release tenet-performance Performance related issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants