Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maximum number of Spring "@Async" calls at a time

I have an async method which i need to call multiple times. Is there any limit that i can have only these many calls at a time? if yes, what is the best way to restrict. Is thread.sleep is fine or is there any other way?

I might need to call the method more than 50k times. In different system its behaving differently with out any restriction. For one system it has completed successfully, where as another one it got stopped in between. Am expecting its because of too many async call

UPDATE sample code

 @Async
        public void download(){
    //download file from server
    }
    public void callDownload(){
    for( int i =0; i <100000; i++)
      download();
    }

Thanks in advance!

like image 348
Sheljith krishnan Avatar asked Oct 29 '25 14:10

Sheljith krishnan


1 Answers

OK so what we are actually talking about is asynchronous calls implemented using the Spring @async mechanism.

According to https://www.baeldung.com/spring-async:

Simply put – annotating a method of a bean with @Async will make it execute in a separate thread; i.e. the caller will not wait for the completion of the called method.

and

By default, Spring uses a SimpleAsyncTaskExecutor to actually run these methods asynchronously.

Looking at the javadocs for SimpleAsyncTaskExecutor, we see:

TaskExecutor implementation that fires up a new Thread for each task, executing it asynchronously.

Supports limiting concurrent threads through the "concurrencyLimit" bean property. By default, the number of concurrent threads is unlimited.

NOTE: This implementation does not reuse threads! Consider a thread-pooling TaskExecutor implementation instead, in particular for executing a large number of short-lived tasks.

So from this we can conclude that (unless you have done some extra tuning that you have not mentioned):

  1. Each one of your asynchronous calls uses a separate thread.
  2. There is no thread pooling to recycle threads.
  3. The mechanism does not limit the number of threads created.

Creating a thread is expensive, and each thread consumes a significant amount of memory. So I expect that what is happening is that you are overloading the JVM with an excessive number of threads, and it is grinding .. to .... a ........ halt. (Either due to a GC death-spiral, virtual memory thrashing or maybe network congestion due to trying to do too many downloads at the same time.)

Basically, this naive approach won't scale. A better idea would be to use an ExecutorService with a bounded thread pool, and submit the download requests as tasks. The executor service will queue the tasks and submit them to its pool of worker threads. You should tune the size of the thread pool so that it doesn't overwhelm your local memory / compute, your network connection ... and the remote servers that you are HAMMERING with parallel downloads.

It is also possible that the remote servers are throttling your downloads ... because your massively parallel downloads look like a DOS attack.

like image 164
Stephen C Avatar answered Oct 31 '25 04:10

Stephen C



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!