Open pedoc opened 1 year ago
@BrennanConroy seems like a job for a rate limiting stream implementation?
The way networking works there are limits to how much you can enforce this on the server side. Even if you're not consuming the data the client can keep sending until it fills up ever network buffer between you and them. If you control the client application, then you can implement far more consistent handling from that end.
Triage: this would make an interesting sample that we could add to our docs (showing both upload speed limiting and download speed limiting)
If we got enough demand for this we may consider adding an in-box feature to support this.
Thanks for contacting us.
We're moving this issue to the .NET 8 Planning
milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.
If you control the client application
This is unlikely, we can't control every browser client and make them upload at 10KB/s, as far as I know it can't be done. Furthermore, even if all clients can be controlled, their cumulative bandwidth may still exceed the limit, and it is difficult to calculate the limit for each client when the number of clients is uncertain. So throttling from the server side is the only option.
If we got enough demand for this we may consider adding an in-box feature to support this.
As far as I know, uploading or downloading can be speed-limited (Qos) by adjusting the "TCP windowing". Of course, this requires the framework to expose the Socket used in the underlying communication in order to control it. Is this currently possible?
The following scenarios will require speed limit support
In addition, including the Spring framework of java, it seems that there is no out-of-the-box support for this function, and it will be more advantageous if it is supported. 😄
+1, it is a nice feature support upload speed limiting and download speed limiting
Note capping download speeds would be much easier, the server controls when and how much data is sent. It should be possible to intercept response body writes with a middleware and Stream shim, and to add delays if the data rate is too fast.
I started putting together a rough sample for capping download speeds. It includes a custom middleware that wraps the response body stream in a ThrottledStream
, which intercepts writes to the stream and adds delays to ensure the download rate stays below the specified limit.
Right now I just have this in a personal repo here david-acker/ThrottlingSample, but I can put up a PR once I polish this a bit. Would this sample live in this repo or in dotnet/AspNetCore.Docs or dotnet/AspNetCore.Docs.Samples?
Edit: Still requires some fixes to address the issue mentioned below.
For the upload scenario, it seems to me that the cure is worse than the disease when it comes to upload throttling. Clients will upload as fast as they can and at the layer that ASP.NET works at you won't really be able to exert any control over the rate at which data is arriving on the box. Once you've got the data on the box, its generally best to store it where you need to store it and free up the resources for another request.
Coming back to the original reason for the requestion:
In some scenarios, we need to limit the file upload speed so as not to affect other services, and reduce the overall load of the machine (cpu, network disk, etc.), is there currently an out-of-the-box function or support for custom implementation?
You've got no real control over network. It will likely cost you more in CPU you manage the throttling, and often disk is actually some other machine on the network (unless the files are quite large and need to be staged on disk before uploading).
@mitchdenny, there is some ability to push back on client uploads by simply limiting how quickly you consume the request body. Yes there are several intermediate buffers, but once they're full TCP will start telling the client to back off. Limiting consumption speed will also limit/spread the CPU used to process the request.
@david-acker, thanks for the sample. I think the throttling methods are incomplete, there's no division to normalize between bytes written and time elapsed. E.g. if the producer takes more than a second to write _maxBytesPerSecond, or the consumer takes more than a second to read it, then _lastWriteTime and _bytesWritten will never be reset and elapsed will be stuck at greater than one second. https://github.com/david-acker/ThrottlingSample/blob/fd19556720c576e2fafe8756ae940a7020ebdc77/src/Middleware/ThrottledStream.cs#L109-L139
@mitchdenny, there is some ability to push back on client uploads by simply limiting how quickly you consume the request body. Yes there are several intermediate buffers, but once they're full TCP will start telling the client to back off. Limiting consumption speed will also limit/spread the CPU used to process the request.
In theory but I'd be surprised if you could do much in practice that would make a different in the application layer.
@Tratcher Finally got around to fixing the normalization issue with bytes written and time elapsed in the sample. I also added some documentation and usage examples to the README.
Sample: david-acker/ThrottlingSample
FWIW I put together a POC for limiting upload speed for tusdotnet back in 2020. See the issue linked by egbakou. The POC worked pretty well when tested on an Azure app service and uploading using Chrome. The idea was the same as @david-acker has here with a throttled stream but applied to the request body stream instead of the response stream.
https://github.com/tusdotnet/tusdotnet/issues/78#issuecomment-577726013
Is there an existing issue for this?
Is your feature request related to a problem? Please describe the problem.
In some scenarios, we need to limit the file upload speed so as not to affect other services, and reduce the overall load of the machine (cpu, network disk, etc.), is there currently an out-of-the-box function or support for custom implementation?
Any help would be greatly appreciated.
Describe the solution you'd like
It would be nice if the framework provided easy configuration options to achieve this goal.
Additional context
No response