-
Notifications
You must be signed in to change notification settings - Fork 10.7k
Rate Limit for Kestrel - Design mechanism to apply back pressure to accepting connections #13295
Copy link
Copy link
Open
Open
Feature
Copy link
Labels
Needs: DesignThis issue requires design work before implementating.This issue requires design work before implementating.Priority:1Work that is critical for the release, but we could probably ship withoutWork that is critical for the release, but we could probably ship withoutaffected-very-fewThis issue impacts very few customersThis issue impacts very few customersarea-middlewareIncludes: URL rewrite, redirect, response cache/compression, session, and other general middlewaresIncludes: URL rewrite, redirect, response cache/compression, session, and other general middlewaresarea-networkingIncludes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractionsIncludes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractionsblockedThe work on this issue is blocked due to some dependencyThe work on this issue is blocked due to some dependencyenhancementThis issue represents an ask for new feature or an enhancement to an existing oneThis issue represents an ask for new feature or an enhancement to an existing onefeature-rate-limitWork related to use of rate limit primitivesWork related to use of rate limit primitivesfeature-yarpThis issue is related to work on yarpThis issue is related to work on yarpseverity-nice-to-haveThis label is used by an internal toolThis label is used by an internal tool🥌 Bedrock
Milestone
Metadata
Metadata
Assignees
Labels
Needs: DesignThis issue requires design work before implementating.This issue requires design work before implementating.Priority:1Work that is critical for the release, but we could probably ship withoutWork that is critical for the release, but we could probably ship withoutaffected-very-fewThis issue impacts very few customersThis issue impacts very few customersarea-middlewareIncludes: URL rewrite, redirect, response cache/compression, session, and other general middlewaresIncludes: URL rewrite, redirect, response cache/compression, session, and other general middlewaresarea-networkingIncludes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractionsIncludes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractionsblockedThe work on this issue is blocked due to some dependencyThe work on this issue is blocked due to some dependencyenhancementThis issue represents an ask for new feature or an enhancement to an existing oneThis issue represents an ask for new feature or an enhancement to an existing onefeature-rate-limitWork related to use of rate limit primitivesWork related to use of rate limit primitivesfeature-yarpThis issue is related to work on yarpThis issue is related to work on yarpseverity-nice-to-haveThis label is used by an internal toolThis label is used by an internal tool🥌 Bedrock
Type
Fields
Give feedbackNo fields configured for Feature.
Is your feature request related to a problem? Please describe.
To match functionality with WCF on .NET Framework, CoreWCF needs to be able to control the number of pending accepts. When a client connects to WCF using the NetTcp transport, there is a handshake that needs to be completed which includes authentication and security upgrade negotiation. After a connection has been established and while the handshake is ongoing, a connection is considered to be a pending connection. WCF controls the maximum number of connections which are in the pending connection state by controlling the maximum number of pending accepts to never be more than how many more pending connections are possible. For example, if the maximum number of pending connections is configured to be 100 and there are currently 95 pending connections, we limit the number of pending accepts to be no more than 5.
Describe the solution you'd like
I believe there should be a generic throttling interface that can be added by DI for use at any layer within an app, and a derived interface (which adds no extra methods) which is used at the transport layer. The two interfaces would be defined as:
When calling AcquireAsync, one of four things can happen.
In the code which calls Accept on the listening socket, if an ITransportThrottleexists in DI, in a loop it acquires the throttle and adds another pending accept until ITransportThrottle.AcquireAsync returns a non-completed ValueTask. It would be up to the implementation of the ITransportThrottleto ensure there's a sensible number of pending accepts. Basically the number of pending accepts is completely controlled by the ITransportThrottleif it exists.
Edit: Changed IServiceThrottle to ITransportThrottle