Skip to content

[Epic] Request Throttling and Queuing Middleware #10702

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

Closed
5 of 10 tasks
analogrelay opened this issue May 31, 2019 · 10 comments
Closed
5 of 10 tasks

[Epic] Request Throttling and Queuing Middleware #10702

analogrelay opened this issue May 31, 2019 · 10 comments
Assignees
Labels
area-middleware Includes: URL rewrite, redirect, response cache/compression, session, and other general middlewares Epic Groups multiple user stories. Can be grouped under a theme.
Milestone

Comments

@analogrelay
Copy link
Contributor

analogrelay commented May 31, 2019

Optimistically putting this in 3.1, but no committments as to when exactly this ships. It won't be part of 3.0.

This is tracking work to add a Request Throttling and Queuing middleware (or possibly middlewares) to ASP.NET Core. The purpose of this is to enable app developers to restrict the number of concurrently-running requests in their application in order to better manage resources.

Currently, the only queuing that occurs in ASP.NET Core applications is through use of the thread-pool queue, which queues completions of async operations (i.e. async/await) and other thread-pool work items. This can be difficult to manage and measure. For some applications, the introduction of a concurrent request limit can mitigate issues caused by problematic async patterns (like "sync-over-async" where blocking calls are done in async code paths). The "Right Thing" to do in most of these cases is to unravel these "sync-over-async" calls into a true async/await pattern, but sometimes that's infeasible or too costly. Limiting concurrent requests conserves these resources.

When there is a concurrent request limit, it is also desirable to "queue" requests that come in over this limit rather than turning them away immediately. This also provides a clear metric to use to measure the impact of load on your system (the number of requests waiting in the queue).

Our goal is to build a middleware that limits the number of concurrently executing requests in the remainder of the pipeline. The middleware will also queue requests beyond that limit until there is space. Finally, if the limit and the queue are exhausted, it will reject the request immediately (usually by emitting a 503 HTTP status code).

We do believe that components of this middleware may be useful for "throttling" as well. Throttling includes scenarios like API Rate Limits, where requests are tracked against certain per-user limits and rejected when they exceed that limit. This is beyond the current scope of the middleware but may serve as a stretch goal.

NOTE: This is our summer intern project, so bear with us as we work through it. We've shipped many of our intern projects as production code in future releases and intend to do so with this one as well!

Child Items:

@rynowak
Copy link
Member

rynowak commented Jun 1, 2019

Can we get some cool info about what this is and how it be what it do?

@halter73
Copy link
Member

halter73 commented Jun 3, 2019

The cliff's note's versions is that this middleware is designed to prevent threadpool starvation just like the System.Web request queue. It will be able to enforce a configurable concurrent request limit and start queuing new requests once the concurrent request limit is reached. Of course, the number of requests that can be queued at once is also configurable. If the request queue fills up, requests will be rejected with a generic 503 or custom handler.

There's still discussion on how useful it might be to allow certain (e.g. admin) requests to bypass the main request queue. That's what "Multiple queues and queue assignment. (Func<HttpContext, Queue>)" is referring to. Whether we just blog about this middleware, include it in some templates, or something else is still up in the air. I doubt it's something we'd be able to turn on by default.

@halter73
Copy link
Member

halter73 commented Jun 3, 2019

Of course, things have changed from the early days of System.Web. Most importantly, a request doesn't necessarily block a thread, but sometimes they do.

@rynowak
Copy link
Member

rynowak commented Jun 3, 2019

Of course, things have changed from the early days of System.Web. Most importantly, a request doesn't necessarily block a thread, but sometimes they do.

This is also something I deffo remember discussing in the early days of K. For whatever reason we didn't built it in, but there was discussion about making this an MVC filter - (middlware is a better choice).

There's still discussion on how useful it might be to allow certain (e.g. admin) requests to bypass the main request queue. That's what "Multiple queues and queue assignment. (Func<HttpContext, Queue>)" is referring to. Whether we just blog about this middleware, include it in some templates, or something else is still up in the air. I doubt it's something we'd be able to turn on by default.

If you end up having this feature, I'd suggest showing a sample that does that based on endpoints and metadata. Then you can slap an attribute on a method to configure the policy.

You might also want to write a generic [QueueName(...)] attribute that can be used with routing to drive all of this. Attributes can be applied to hubs/grpc/controllers/pages, and can also be used with routerware (middleware pipeline + route + metadata like auth policies).

@analogrelay
Copy link
Contributor Author

Multiple queues are a 💪 stretch goal right now anyway :). But this is good stuff to consider when we get there.

@dazinator
Copy link

dazinator commented Jun 3, 2019

Will it be possible to say, add the Queing middleware after Authentication middleware? So for example, authenticated user traffic could be prioritised? If user name = "dazinator" he always gets to skip the queue ? ;-)

@halter73
Copy link
Member

halter73 commented Jun 3, 2019

So for example, authenticated user traffic could be prioritized?

If we reach our stretch goal and get multi-queue support, that should be possible.

@Kahbazi
Copy link
Member

Kahbazi commented Jun 3, 2019

Do you also have plans to add throttling based on time like https://github.com/stefanprodan/AspNetCoreRateLimit? for example a user can call a api 10 times per second. and as @rynowak mentioned it would be a good feature to wire up these middlewares to endpoint metadata

@analogrelay
Copy link
Contributor Author

analogrelay commented Jun 3, 2019

Our plans (for now) are limited to what you see above :). Simple front-door queueing is what we're starting with, we do have some ideas around integrating throttling moving forward but that may also end up as a separate middleware.

@analogrelay
Copy link
Contributor Author

Closing for now, we don't have plans to go further here in 5.0. Individual work items are still on the backlog.

@ghost ghost locked as resolved and limited conversation to collaborators Apr 17, 2020
@amcasey amcasey added area-middleware Includes: URL rewrite, redirect, response cache/compression, session, and other general middlewares and removed area-runtime labels Jun 2, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-middleware Includes: URL rewrite, redirect, response cache/compression, session, and other general middlewares Epic Groups multiple user stories. Can be grouped under a theme.
Projects
None yet
Development

No branches or pull requests

8 participants