0

I have a database with around 900 records. I need to send each record's info onto a government server and get a response back to update to database. 1 cycle response request takes around 0.3s and so it takes around 5 min to complete the whole task.

I am looking to do it asynchronously. However, it would iterate 900 records in an instant and swamp the server with 900 request in a miniscule amount of time. I am afraid I will DDOS it.

My solution is:

  1. to send them in a batch, like ~30 records each (or any relatively small number). The batch is just a c# List holding the async Tasks.

  2. Then using Task.WhenAny() to detect finished tasks, remove them of the off the list and add new async task to it. That way I can keep my requests to a small number.

Is my worry justified and my approach correct? Is there any already available library to limit the number of requests send like this?

Any thought and advice would be appreciated!

Tri
  • 199
  • 9
  • You could try using Parallel.For: https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.parallel.for?view=net-5.0 Using the ParallelOptions, you can set the max degree of parallelism so that you can control how many threads are running asynchronously while also not having to have the extra logic to wait and move on to the next batch – emagers Oct 21 '21 at 15:27
  • DDOS normally means millions to billions of requests per minute over an extended period. 900 requests isn't too much and any basic server should be able to handle it in a matter of a minute give or take. Whether you can do this or not, you need to check usage policies. Also, asynchronously != in parallel. – Camilo Terevinto Oct 21 '21 at 15:27
  • See also https://stackoverflow.com/q/36564596/15393 – RB. Oct 21 '21 at 15:27
  • 2
    @EricMagers / RB - The Parallel methods aren't good for async methods – Camilo Terevinto Oct 21 '21 at 15:29
  • @EricMagers This is I/O-bound tasks. I don't think using Task Parallel library is recommended by Microsoft. Source: https://learn.microsoft.com/en-us/dotnet/csharp/async. It should be used for CPU-bound tasks only. But thank you anyway! – Tri Oct 21 '21 at 15:37
  • @TríNguyễn The Task Parallel Library is a library specifically for asynchronous code. A task is a Future, an abstraction around an arbitrary asynchronous operation. It's just the `Parallel` class specifically (which has nothing to do with the TPL) that's designed for synchronous code. – Servy Oct 21 '21 at 15:54
  • There are basically two policies for throttling parallel operations. Throttle the concurrency or throttle the rate. Limiting the concurrency means that no more than X operations will ever be in-flight concurrently. Limiting the rate means that no more than X operations will ever be started during any Y time span. Which of the two throttling policies are you inclined to implement? – Theodor Zoulias Oct 21 '21 at 16:52
  • @TríNguyễn `Parallel.ForEach` is meant for data parallelism - processing a lot of in-memory data using all available cores by partitioning the data and having each core process one partition. That's clearly not the case here. What you have is a few HTTP request that need to be executed with a fixed DOP and/or limit. `async` **won't** iterate all requests in an instant, it would execute them one by one. Obviously your code is doing something strange like generating all requests with a `Select`. There are several ways to avoid this – Panagiotis Kanavos Oct 21 '21 at 17:31
  • @TríNguyễn in .NET 6 you can use `Parallel.ForEach*Async*` which was specifically created for this case. In all supported .NET versions you can use ActionBlock to process messages (eg URLs) posted to it with a fixed Degree-of-Parallelism (DOP). You can add a small delay after each request to reduce the rate at which each worker task sends requests – Panagiotis Kanavos Oct 21 '21 at 17:33

0 Answers0